wolfhece 2.1.115__py3-none-any.whl → 2.1.117__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.
wolfhece/PyDraw.py CHANGED
@@ -129,6 +129,44 @@ ID_PLOTCS = 1003 #Manageactions ID for profile plots
129
129
 
130
130
  LIST_1TO9 = [wx.WXK_NUMPAD1, wx.WXK_NUMPAD2, wx.WXK_NUMPAD3, wx.WXK_NUMPAD4, wx.WXK_NUMPAD5, wx.WXK_NUMPAD6, wx.WXK_NUMPAD7, wx.WXK_NUMPAD8, wx.WXK_NUMPAD9 ] + [ord(str(cur)) for cur in range(1,10)]
131
131
 
132
+ PROJECT_ACTION = 'action'
133
+ PROJECT_CS = 'cross_sections'
134
+ PROJECT_VECTOR = 'vector'
135
+ PROJECT_ARRAY = 'array'
136
+ PROJECT_TILES = 'tiles'
137
+ PROJECT_LAZ = 'laz_grid'
138
+ PROJECT_CLOUD = 'cloud'
139
+ PROJECT_WOLF2D = 'wolf2d'
140
+ PROJECT_GPU2D = 'gpu2d'
141
+ PROJECT_PALETTE = 'palette'
142
+ PROJECT_PALETTE_ARRAY = 'palette-array'
143
+ PROJECT_LINK_CS = 'cross_sections_link'
144
+ PROJECT_LINK_VEC_ARRAY = 'vector_array_link'
145
+
146
+ PROJECT_GROUP_KEYS = {PROJECT_ACTION : {'which': 'compare_arrays'},
147
+ PROJECT_CS: {'id - file': 'id to use - full or relative path to CS file',
148
+ 'format': '(mandatory) 2000, 2022, vecz, sxy',
149
+ 'dirlaz': 'Path to LAZ data (prepro Numpy)'},
150
+ PROJECT_VECTOR: {'id - file': 'id to use - full or relative path to vector file (.vec, .vecz, .shp)'},
151
+ PROJECT_ARRAY: {'id - file': 'id to use - full or relative path to array file (.bin, .tif, .npy, .npz)'},
152
+ PROJECT_TILES : {'id': '(mandatory) id to use',
153
+ 'tiles_file': '(mandatory) Path to tiles file',
154
+ 'data_dir': '(mandatory) Path to data directory',
155
+ 'comp_dir': 'Path to comparison directory'},
156
+ PROJECT_LAZ: {'data_dir': '(mandatory) Path to data directory (prepro Numpy)',
157
+ 'classification': 'Color classification for LAZ data - default SPW-Geofit 2023',},
158
+ PROJECT_CLOUD: {'id - file': 'id to use - full or relative path to cloud file (.xyz, .txt)'},
159
+ PROJECT_WOLF2D: {'id - dir': 'id to use - full or relative path to wolf2d simulation directory'},
160
+ PROJECT_GPU2D: {'id - dir': 'id to use - full or relative path to gpu2d simulation directory'},
161
+ PROJECT_PALETTE : {'id - file': 'id to use - full or relative path to palette file (.pal)'},
162
+ PROJECT_PALETTE_ARRAY : {'idarray - idpal': 'id of array - id of palette to link'},
163
+ PROJECT_LINK_CS : {'linkzones' : '(mandatory) id of vector to link to cross sections',
164
+ 'sortzone' : '(mandatory) id of the zone to use for sorting',
165
+ 'sortname' : '(mandatory) id of the polyline to use for sorting',
166
+ 'downfirst' : 'is the first vertex downstream or upstream? (1 is True, 0 is False - default is False)'},
167
+ PROJECT_LINK_VEC_ARRAY : {'id - id vector': 'id of array/wolf2d/gpu2d - id of vector to link (only 1 vector in 1 zone)'},
168
+ }
169
+
132
170
  class Memory_View():
133
171
  """ Memory view """
134
172
 
@@ -1232,6 +1270,8 @@ class WolfMapViewer(wx.Frame):
1232
1270
  self.linkedList = None
1233
1271
  self.link_params = None
1234
1272
 
1273
+ self.project_pal = None
1274
+
1235
1275
  self.forcemimic = True
1236
1276
  self.currently_readresults = False
1237
1277
 
@@ -1269,8 +1309,8 @@ class WolfMapViewer(wx.Frame):
1269
1309
  self.menuimagestiles = None
1270
1310
 
1271
1311
  self.filemenu = wx.Menu()
1272
- openitem = self.filemenu.Append(wx.ID_OPEN, _('Open project'), _('Open a complete project from file'))
1273
- saveproject = self.filemenu.Append(wx.ID_ANY, _('Save project'), _('Save the current project to file'))
1312
+ openitem = self.filemenu.Append(wx.ID_OPEN, _('Open/Add project'), _('Open a complete project from file'))
1313
+ saveproject = self.filemenu.Append(wx.ID_ANY, _('Save project as...'), _('Save the current project to file'))
1274
1314
  self.filemenu.AppendSeparator()
1275
1315
  saveitem = self.filemenu.Append(wx.ID_SAVE, _('Save'), _('Save all checked arrays or vectors to files'))
1276
1316
  saveasitem = self.filemenu.Append(wx.ID_SAVEAS, _('Save as...'), _('Save all checked arrays or vectors to new files --> one file dialog per data'))
@@ -1517,6 +1557,7 @@ class WolfMapViewer(wx.Frame):
1517
1557
  # Help
1518
1558
  self.helpmenu = wx.Menu()
1519
1559
  self.helpmenu.Append(wx.ID_ANY, _('Shortcuts'), _('Shortcuts'))
1560
+ self.helpmenu.Append(wx.ID_ANY, _('Project .proj'), _('A project file ".proj", what is it?'))
1520
1561
  self.helpmenu.Append(wx.ID_ANY, _('Show logs/informations'), _('Logs'))
1521
1562
  self.helpmenu.Append(wx.ID_ANY, _('Show values'), _('Data/Values'))
1522
1563
  self.helpmenu.Append(wx.ID_ANY, _('About'), _('About'))
@@ -2283,21 +2324,33 @@ class WolfMapViewer(wx.Frame):
2283
2324
  dlg.Destroy()
2284
2325
  return
2285
2326
 
2286
- for curmodel in self.iterator_over_objects(draw_type.RES2D):
2327
+ pgbar = wx.ProgressDialog(_('Setting epsilon'), _('Setting epsilon'), maximum = len(self.myres2D), parent=self, style = wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
2328
+
2329
+ for id, curmodel in enumerate(self.iterator_over_objects(draw_type.RES2D)):
2287
2330
  curmodel: Wolfresults_2D
2288
2331
  curmodel.epsilon = neweps
2289
2332
  curmodel._epsilon_default = neweps
2290
2333
  curmodel.read_oneresult(curmodel.current_result)
2291
2334
  curmodel.set_currentview()
2292
2335
 
2336
+ pgbar.Update(id, _('Setting epsilon for result {}'.format(curmodel.idx)))
2337
+
2338
+ pgbar.Destroy()
2339
+
2293
2340
  elif itemlabel == _("Filter independent"):
2294
2341
 
2295
2342
  self.menu_filter_independent.IsChecked = not self.menu_filter_independent.IsChecked
2296
2343
 
2297
- for curmodel in self.iterator_over_objects(draw_type.RES2D):
2344
+ pgbar = wx.ProgressDialog(_('Filtering independent zones'), _('Filtering independent zones'), maximum = len(self.myres2D), parent=self, style = wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
2345
+
2346
+ for id, curmodel in enumerate(self.iterator_over_objects(draw_type.RES2D)):
2298
2347
  curmodel: Wolfresults_2D
2299
2348
  curmodel.to_filter_independent = not self.menu_filter_independent.IsChecked
2300
2349
 
2350
+ pgbar.Update(id, _('Filtering independent zones for result {}'.format(curmodel.idx)))
2351
+
2352
+ pgbar.Destroy()
2353
+
2301
2354
  # elif itemlabel == _("Manage boundary conditions..."):
2302
2355
 
2303
2356
  # if self.active_res2d is not None:
@@ -2988,6 +3041,26 @@ class WolfMapViewer(wx.Frame):
2988
3041
  else:
2989
3042
  return config[ConfigurationKeys.TICKS_SIZE]
2990
3043
 
3044
+ @property
3045
+ def ticks_xrotation(self) -> float:
3046
+ """ Return the ticks x rotation from configs """
3047
+
3048
+ config = self.get_configuration()
3049
+ if config is None:
3050
+ return 30.
3051
+ else:
3052
+ return config[ConfigurationKeys.TICKS_XROTATION]
3053
+
3054
+ @property
3055
+ def ticks_fontsize(self) -> int:
3056
+ """ Return the ticks font size from configs """
3057
+
3058
+ config = self.get_configuration()
3059
+ if config is None:
3060
+ return 14
3061
+ else:
3062
+ return config[ConfigurationKeys.TICKS_FONTSIZE]
3063
+
2991
3064
  @property
2992
3065
  def assembly_mode(self) -> str:
2993
3066
  """ Return the assembly mode from configs """
@@ -3182,187 +3255,10 @@ class WolfMapViewer(wx.Frame):
3182
3255
  return
3183
3256
  self.start_action('rotate triangles', 'Rotate the current triangulation -- Please select 1 point for the center')
3184
3257
 
3185
- def copy_canvasogl(self, mpl:bool= True, ds:float= 0., figsizes= [10.,10.], palette:wolfpalette = None):
3186
- """
3187
- Generate image based on UI context and copy to the Clipboard
3188
3258
 
3189
- :param mpl: Using Matplolib as renderer. Defaults to True.
3190
- :type mpl: bool, optional
3191
- :parem ds: Ticks size. Defaults to 0..
3192
- :type ds: float, optional
3193
- :parem figsizes: fig size in inches
3194
- :type figsizes: list, optional
3195
- """
3196
-
3197
- if wx.TheClipboard.Open():
3198
- self.Paint()
3199
-
3200
- if self.SetCurrentContext():
3201
-
3202
- myimage = self.get_canvas_as_image()
3203
-
3204
- # # Récupération du buffer OpenGL
3205
- # glPixelStorei(GL_PACK_ALIGNMENT, 1)
3206
- # data = glReadPixels(0, 0, self.canvaswidth, self.canvasheight, GL_RGBA, GL_UNSIGNED_BYTE)
3207
- # # Création d'une image sur base du buffer
3208
- # myimage: Image.Image
3209
- # myimage = Image.frombuffer("RGBA", (self.canvaswidth, self.canvasheight), data)
3210
- # # On tranpose car OpenGL travaille avec comme référence le coin inférieur gauche
3211
- # myimage = myimage.transpose(1)
3212
-
3213
- metadata = PngInfo()
3214
- metadata.add_text('xmin', str(self.xmin))
3215
- metadata.add_text('ymin', str(self.ymin))
3216
- metadata.add_text('xmax', str(self.xmax))
3217
- metadata.add_text('ymax', str(self.ymax))
3218
-
3219
- if mpl:
3220
- if ds == 0.:
3221
- ds = self.ticks_size # Global parameters
3222
-
3223
- if ds == 0.:
3224
- ds = 100.
3225
-
3226
- nb_ticks_x = (self.xmax - self.xmin) // ds
3227
- nb_ticks_y = (self.ymax - self.ymin) // ds
3228
-
3229
- if nb_ticks_x > 10 or nb_ticks_y > 10:
3230
- logging.error(_('Too many ticks for the image. Please raise the ticks size in the global options.'))
3231
- return
3232
-
3233
- # Création d'une graphique Matplotlib
3234
- extent = (self.xmin, self.xmax, self.ymin, self.ymax)
3235
- fig, ax = plt.subplots(1, 1)
3236
-
3237
- w, h = [self.width, self.height]
3238
-
3239
- # neww = figsizes[0]/figsizes[1] *h
3240
- neww = figsizes[0]
3241
- newh = h/w * figsizes[0]
3242
-
3243
- fig.set_size_inches(neww, newh)
3244
-
3245
- pos = ax.imshow(myimage,
3246
- origin='upper',
3247
- extent=extent)
3248
-
3249
- x1 = np.ceil((self.xmin // ds) * ds)
3250
- if x1 < self.xmin:
3251
- x1 += ds
3252
- x2 = int((self.xmax // ds) * ds)
3253
- if x2 > self.xmax:
3254
- x2 -= ds
3255
- y1 = np.ceil((self.ymin // ds) * ds)
3256
- if y1 < self.ymin:
3257
- y1 += ds
3258
- y2 = int((self.ymax // ds) * ds)
3259
- if y2 > self.ymax:
3260
- y2 -= ds
3261
-
3262
- x_label_list = np.linspace(x1, x2, int((x2 - x1) / ds) + 1, True)
3263
- if self.ticks_bounds:
3264
- x_label_list = np.insert(x_label_list, 0, self.xmin)
3265
- x_label_list = np.insert(x_label_list, -1, self.xmax)
3266
- x_label_list = np.unique(x_label_list)
3267
-
3268
- y_label_list = np.linspace(y1, y2, int((y2 - y1) / ds) + 1, True)
3269
- if self.ticks_bounds:
3270
- y_label_list = np.insert(y_label_list, 0, self.ymin)
3271
- y_label_list = np.insert(y_label_list, -1, self.ymax)
3272
- y_label_list = np.unique(y_label_list)
3273
-
3274
- ax.set_xticks(x_label_list)
3275
- ax.set_yticks(y_label_list)
3276
-
3277
- ax.set_xticklabels(plt.FormatStrFormatter('%.1f').format_ticks(x_label_list), fontsize=14, rotation=30)
3278
- ax.set_yticklabels(plt.FormatStrFormatter('%.1f').format_ticks(y_label_list), fontsize=14)
3279
-
3280
- ax.set_xlabel('X [m]')
3281
- ax.set_ylabel('Y [m]')
3282
-
3283
- #création de 2 buffers
3284
- buf = io.BytesIO()
3285
- #sauvegarde de la figure au format png
3286
- fig.tight_layout()
3287
- fig.savefig(buf, format='png')
3288
-
3289
- #déplacement au début du buffer
3290
- buf.seek(0)
3291
- #lecture du buffer et conversion en image avec PIL
3292
- im = Image.open(buf)
3293
-
3294
- if palette is None:
3295
- palette = self.palette_for_copy
3296
- # if self.active_array is not None:
3297
- # palette = self.active_array.mypal
3298
- # elif self.active_res2d is not None:
3299
- # palette = self.active_res2d.mypal
3300
-
3301
- if palette is not None:
3302
- if palette.values is not None:
3303
- bufpal = io.BytesIO()
3304
- palette.export_image(bufpal,'v')
3305
- bufpal.seek(0)
3306
-
3307
- #lecture du buffer et conversion en image avec PIL
3308
- impal = Image.open(bufpal)
3309
- impal = impal.resize((int(impal.size[0]*im.size[1]*.8/impal.size[1]),int(im.size[1]*.8)))
3310
-
3311
- imnew = Image.new('RGB',(im.size[0]+impal.size[0], im.size[1]), (255,255,255))
3312
-
3313
- # On colle l'image du buffer et la palette pour ne former qu'une seul image à copier dans le clipboard
3314
- imnew.paste(im.convert('RGB'),(0,0))
3315
- imnew.paste(impal.convert('RGB'),(im.size[0]-10, int((im.size[1]-impal.size[1])/3)))
3316
- im=imnew
3317
- else:
3318
- imnew = Image.new('RGB', (im.size[0], im.size[1]), (255,255,255))
3319
-
3320
- # On colle l'image du buffer et la palette pour ne former qu'une seul image à copier dans le clipboard
3321
- imnew.paste(im.convert('RGB'),(0,0))
3322
- im=imnew
3323
- else:
3324
- imnew = Image.new('RGB', (im.size[0], im.size[1]), (255,255,255))
3325
-
3326
- # On colle l'image du buffer et la palette pour ne former qu'une seul image à copier dans le clipboard
3327
- imnew.paste(im.convert('RGB'),(0,0))
3328
- im=imnew
3329
-
3330
- #création d'un objet bitmap wx
3331
- wxbitmap = wx.Bitmap().FromBuffer(im.width,im.height,im.tobytes())
3332
-
3333
- # objet wx exportable via le clipboard
3334
- dataobj = wx.BitmapDataObject()
3335
- dataobj.SetBitmap(wxbitmap)
3336
-
3337
- wx.TheClipboard.SetData(dataobj)
3338
- wx.TheClipboard.Close()
3339
-
3340
- fig.set_visible(False)
3341
-
3342
- buf.close()
3343
-
3344
- return fig, ax, im
3345
-
3346
- else:
3347
- """ Création d'un objet bitmap wx sur base du canvas
3348
- et copie dans le clipboard
3349
- """
3350
- # wxbitmap = wx.Bitmap().FromBuffer(myimage.width,myimage.height,myimage.tobytes())
3351
- wxbitmap = wx.Bitmap().FromBufferRGBA(myimage.width,myimage.height,myimage.tobytes())
3352
-
3353
- # objet wx exportable via le clipboard
3354
- dataobj = wx.BitmapDataObject()
3355
- dataobj.SetBitmap(wxbitmap)
3356
-
3357
- wx.TheClipboard.SetData(dataobj)
3358
- wx.TheClipboard.Close()
3359
-
3360
- return myimage
3361
-
3362
- else:
3363
- wx.MessageBox("Can't open the clipboard", "Error")
3364
-
3365
- def display_canvasogl(self,mpl =True, ds=0., fig: Figure = None, ax: Axes = None, clear = True, redraw =True, palette=False, title=''):
3259
+ def display_canvasogl(self, mpl =True,
3260
+ ds=0., fig: Figure = None, ax: Axes = None,
3261
+ clear = True, redraw =True, palette=False, title=''):
3366
3262
  """
3367
3263
  This method takes a matplotlib figure and axe and,
3368
3264
  returns a clear screenshot of the information displayed in the wolfpy GUI.
@@ -3418,19 +3314,22 @@ class WolfMapViewer(wx.Frame):
3418
3314
  myax.set_xticks(x_label_list)
3419
3315
  myax.set_yticks(y_label_list)
3420
3316
 
3421
- myax.set_xticklabels(FormatStrFormatter('%.1f').format_ticks(x_label_list), fontsize = 'xx-small', rotation = 90)
3422
- myax.set_yticklabels(FormatStrFormatter('%.1f').format_ticks(y_label_list), fontsize='xx-small')
3317
+ myax.set_xticklabels(FormatStrFormatter('%.1f').format_ticks(x_label_list),
3318
+ fontsize = self.ticks_fontsize, rotation = self.ticks_xrotation)
3319
+ myax.set_yticklabels(FormatStrFormatter('%.1f').format_ticks(y_label_list),
3320
+ fontsize = self.ticks_fontsize)
3423
3321
  myax.xaxis.set_ticks_position('top')
3424
3322
  myax.xaxis.set_label_position('top')
3425
3323
 
3426
- myax.set_xlabel('X - coordinates ($m$)')
3427
- myax.set_ylabel('Y - coordinates ($m$)')
3324
+ myax.set_xlabel('X ($m$)')
3325
+ myax.set_ylabel('Y ($m$)')
3428
3326
  myax.xaxis.set_ticks_position('bottom')
3429
3327
  myax.xaxis.set_label_position('bottom')
3430
3328
 
3431
3329
  if title!='':
3432
3330
  myax.set_title(title)
3433
3331
 
3332
+ fig.tight_layout()
3434
3333
  fig.canvas.draw()
3435
3334
  fig.canvas.flush_events()
3436
3335
 
@@ -3605,12 +3504,188 @@ class WolfMapViewer(wx.Frame):
3605
3504
 
3606
3505
  return myimage
3607
3506
 
3507
+ def copy_canvasogl(self, mpl:bool= True, ds:float= 0., figsizes= [10.,10.], palette:wolfpalette = None):
3508
+ """
3509
+ Generate image based on UI context and copy to the Clipboard
3510
+
3511
+ :param mpl: Using Matplolib as renderer. Defaults to True.
3512
+ :type mpl: bool, optional
3513
+ :parem ds: Ticks size. Defaults to 0..
3514
+ :type ds: float, optional
3515
+ :parem figsizes: fig size in inches
3516
+ :type figsizes: list, optional
3517
+ """
3518
+
3519
+ if wx.TheClipboard.Open():
3520
+ self.Paint()
3521
+
3522
+ if self.SetCurrentContext():
3523
+
3524
+ myimage = self.get_canvas_as_image()
3525
+
3526
+ metadata = PngInfo()
3527
+ metadata.add_text('xmin', str(self.xmin))
3528
+ metadata.add_text('ymin', str(self.ymin))
3529
+ metadata.add_text('xmax', str(self.xmax))
3530
+ metadata.add_text('ymax', str(self.ymax))
3531
+
3532
+ if mpl:
3533
+ if ds == 0.:
3534
+ ds = self.ticks_size # Global parameters
3535
+
3536
+ if ds == 0.:
3537
+ ds = 100.
3538
+
3539
+ nb_ticks_x = (self.xmax - self.xmin) // ds
3540
+ nb_ticks_y = (self.ymax - self.ymin) // ds
3541
+
3542
+ if nb_ticks_x > 10 or nb_ticks_y > 10:
3543
+ logging.error(_('Too many ticks for the image. Please raise the ticks size in the global options.'))
3544
+ return
3545
+
3546
+ # Création d'un graphique Matplotlib
3547
+ extent = (self.xmin, self.xmax, self.ymin, self.ymax)
3548
+ fig, ax = plt.subplots(1, 1)
3549
+
3550
+ w, h = [self.width, self.height]
3551
+
3552
+ neww = figsizes[0]
3553
+ newh = h/w * figsizes[0]
3554
+
3555
+ fig.set_size_inches(neww, newh)
3556
+
3557
+ pos = ax.imshow(myimage,
3558
+ origin='upper',
3559
+ extent=extent)
3560
+
3561
+ x1 = np.ceil((self.xmin // ds) * ds)
3562
+ if x1 < self.xmin:
3563
+ x1 += ds
3564
+ x2 = int((self.xmax // ds) * ds)
3565
+ if x2 > self.xmax:
3566
+ x2 -= ds
3567
+ y1 = np.ceil((self.ymin // ds) * ds)
3568
+ if y1 < self.ymin:
3569
+ y1 += ds
3570
+ y2 = int((self.ymax // ds) * ds)
3571
+ if y2 > self.ymax:
3572
+ y2 -= ds
3573
+
3574
+ x_label_list = np.linspace(x1, x2, int((x2 - x1) / ds) + 1, True)
3575
+ if self.ticks_bounds:
3576
+ x_label_list = np.insert(x_label_list, 0, self.xmin)
3577
+ x_label_list = np.insert(x_label_list, -1, self.xmax)
3578
+ x_label_list = np.unique(x_label_list)
3579
+
3580
+ y_label_list = np.linspace(y1, y2, int((y2 - y1) / ds) + 1, True)
3581
+ if self.ticks_bounds:
3582
+ y_label_list = np.insert(y_label_list, 0, self.ymin)
3583
+ y_label_list = np.insert(y_label_list, -1, self.ymax)
3584
+ y_label_list = np.unique(y_label_list)
3585
+
3586
+ ax.set_xticks(x_label_list)
3587
+ ax.set_yticks(y_label_list)
3588
+
3589
+ ax.set_xticklabels(plt.FormatStrFormatter('%.1f').format_ticks(x_label_list),
3590
+ fontsize = self.ticks_fontsize, rotation = self.ticks_xrotation)
3591
+ ax.set_yticklabels(plt.FormatStrFormatter('%.1f').format_ticks(y_label_list),
3592
+ fontsize = self.ticks_fontsize)
3593
+
3594
+ ax.set_xlabel('X ($m$)')
3595
+ ax.set_ylabel('Y ($m$)')
3596
+
3597
+ fig.tight_layout()
3598
+
3599
+ #création d'un'buffers
3600
+ buf = io.BytesIO()
3601
+ #sauvegarde de la figure au format png
3602
+ fig.savefig(buf, format='png')
3603
+
3604
+ #déplacement au début du buffer
3605
+ buf.seek(0)
3606
+ #lecture du buffer et conversion en image avec PIL
3607
+ im = Image.open(buf)
3608
+
3609
+ if palette is None:
3610
+ palette = self.palette_for_copy
3611
+ # if self.active_array is not None:
3612
+ # palette = self.active_array.mypal
3613
+ # elif self.active_res2d is not None:
3614
+ # palette = self.active_res2d.mypal
3615
+
3616
+ if palette is not None:
3617
+ if palette.values is not None:
3618
+ bufpal = io.BytesIO()
3619
+ palette.export_image(bufpal,'v')
3620
+ bufpal.seek(0)
3621
+
3622
+ #lecture du buffer et conversion en image avec PIL
3623
+ impal = Image.open(bufpal)
3624
+ impal = impal.resize((int(impal.size[0]*im.size[1]*.8/impal.size[1]),int(im.size[1]*.8)))
3625
+
3626
+ imnew = Image.new('RGB',(im.size[0]+impal.size[0], im.size[1]), (255,255,255))
3627
+
3628
+ # On colle l'image du buffer et la palette pour ne former qu'une seul image à copier dans le clipboard
3629
+ imnew.paste(im.convert('RGB'),(0,0))
3630
+ imnew.paste(impal.convert('RGB'),(im.size[0]-10, int((im.size[1]-impal.size[1])/3)))
3631
+ im=imnew
3632
+ bufpal.close()
3633
+ else:
3634
+ imnew = Image.new('RGB', (im.size[0], im.size[1]), (255,255,255))
3635
+
3636
+ # On colle l'image du buffer et la palette pour ne former qu'une seul image à copier dans le clipboard
3637
+ imnew.paste(im.convert('RGB'),(0,0))
3638
+ im=imnew
3639
+ else:
3640
+ imnew = Image.new('RGB', (im.size[0], im.size[1]), (255,255,255))
3641
+
3642
+ # On colle l'image du buffer et la palette pour ne former qu'une seul image à copier dans le clipboard
3643
+ imnew.paste(im.convert('RGB'),(0,0))
3644
+ im=imnew
3645
+
3646
+ #création d'un objet bitmap wx
3647
+ wxbitmap = wx.Bitmap().FromBuffer(im.width,im.height,im.tobytes())
3648
+
3649
+ # objet wx exportable via le clipboard
3650
+ dataobj = wx.BitmapDataObject()
3651
+ dataobj.SetBitmap(wxbitmap)
3652
+
3653
+ wx.TheClipboard.SetData(dataobj)
3654
+ wx.TheClipboard.Close()
3655
+
3656
+ fig.set_visible(False)
3657
+
3658
+ buf.close()
3659
+
3660
+ return fig, ax, im
3661
+
3662
+ else:
3663
+ """ Création d'un objet bitmap wx sur base du canvas
3664
+ et copie dans le clipboard
3665
+ """
3666
+ # wxbitmap = wx.Bitmap().FromBuffer(myimage.width,myimage.height,myimage.tobytes())
3667
+ wxbitmap = wx.Bitmap().FromBufferRGBA(myimage.width,myimage.height,myimage.tobytes())
3668
+
3669
+ # objet wx exportable via le clipboard
3670
+ dataobj = wx.BitmapDataObject()
3671
+ dataobj.SetBitmap(wxbitmap)
3672
+
3673
+ wx.TheClipboard.SetData(dataobj)
3674
+ wx.TheClipboard.Close()
3675
+
3676
+ return myimage
3677
+
3678
+ else:
3679
+ wx.MessageBox("Can't open the clipboard", "Error")
3680
+
3608
3681
  def save_canvasogl(self,
3609
3682
  fn:str='',
3610
3683
  mpl:bool=True,
3611
3684
  ds:float=0.,
3612
3685
  dpi:int= 300,
3613
- add_title:bool = False):
3686
+ add_title:bool = False,
3687
+ figsizes= [10.,10.],
3688
+ arrayid_as_title:bool = False):
3614
3689
  """
3615
3690
  Sauvegarde de la fenêtre d'affichage dans un fichier
3616
3691
 
@@ -3619,6 +3694,7 @@ class WolfMapViewer(wx.Frame):
3619
3694
  :param ds: Ticks interval
3620
3695
  """
3621
3696
 
3697
+ # FIXME : SHOULD BE MERGEd WITH copy_canvasogl
3622
3698
  fn = str(fn)
3623
3699
 
3624
3700
  if fn == '':
@@ -3634,19 +3710,7 @@ class WolfMapViewer(wx.Frame):
3634
3710
  fn += '.png'
3635
3711
 
3636
3712
  if self.SetCurrentContext():
3637
- # glPixelStorei(GL_PACK_ALIGNMENT, 1)
3638
- # data = glReadPixels(0, 0, self.canvaswidth, self.canvasheight, GL_RGBA, GL_UNSIGNED_BYTE)
3639
- # myimage: Image.Image
3640
- # myimage = Image.frombuffer("RGBA", (self.canvaswidth, self.canvasheight), data)
3641
- # myimage = myimage.transpose(1)
3642
-
3643
- myimage = self.get_canvas_as_image()
3644
-
3645
- metadata = PngInfo()
3646
- metadata.add_text('xmin', str(self.xmin))
3647
- metadata.add_text('ymin', str(self.ymin))
3648
- metadata.add_text('xmax', str(self.xmax))
3649
- metadata.add_text('ymax', str(self.ymax))
3713
+ self.Paint()
3650
3714
 
3651
3715
  if mpl:
3652
3716
  if ds == 0.:
@@ -3664,69 +3728,70 @@ class WolfMapViewer(wx.Frame):
3664
3728
  ds = float(dlg.GetValue())
3665
3729
  dlg.Destroy()
3666
3730
 
3731
+ # Création d'un graphique Matplotlib
3667
3732
  extent = (self.xmin, self.xmax, self.ymin, self.ymax)
3668
- # fig, ax = plt.subplots(1, 1)
3669
- fig,axes = plt.subplots(1,2, gridspec_kw={'width_ratios': [20, 1]})
3733
+ fig, ax = plt.subplots(1, 1)
3734
+ w, h = [self.width, self.height]
3670
3735
 
3671
- ax = axes[0]
3672
- self.display_canvasogl(fig=fig,ax=axes[0])
3736
+ neww = figsizes[0]
3737
+ newh = h/w * figsizes[0]
3673
3738
 
3674
- # pos = ax.imshow(myimage, origin='upper',
3675
- # extent=extent)
3676
- # fig.colorbar(pos,ax=ax)
3739
+ fig.set_size_inches(neww, newh)
3677
3740
 
3678
- x1 = np.ceil((self.xmin // ds) * ds)
3679
- if x1 < self.xmin:
3680
- x1 += ds
3681
- x2 = int((self.xmax // ds) * ds)
3682
- if x2 > self.xmax:
3683
- x2 -= ds
3684
- y1 = np.ceil((self.ymin // ds) * ds)
3685
- if y1 < self.ymin:
3686
- y1 += ds
3687
- y2 = int((self.ymax // ds) * ds)
3688
- if y2 > self.ymax:
3689
- y2 -= ds
3741
+ pot_title = self.viewer_name
3742
+ if arrayid_as_title:
3743
+ pot_title = self.active_array.idx
3690
3744
 
3691
- x_label_list = np.linspace(x1, x2, int((x2 - x1) / ds) + 1, True)
3692
- x_label_list = np.insert(x_label_list, 0, self.xmin)
3693
- x_label_list = np.insert(x_label_list, -1, self.xmax)
3694
- x_label_list = np.unique(x_label_list)
3745
+ self.display_canvasogl(fig=fig,
3746
+ ax=ax,
3747
+ title=pot_title if add_title else '',
3748
+ ds = ds)
3695
3749
 
3696
- y_label_list = np.linspace(y1, y2, int((y2 - y1) / ds) + 1, True)
3697
- y_label_list = np.insert(y_label_list, 0, self.ymin)
3698
- y_label_list = np.insert(y_label_list, -1, self.ymax)
3699
- y_label_list = np.unique(y_label_list)
3750
+ #création d'un'buffers
3751
+ buf = io.BytesIO()
3752
+ #sauvegarde de la figure au format png
3753
+ fig.savefig(buf, format='png')
3700
3754
 
3701
- ax.set_xticks(x_label_list)
3702
- ax.set_yticks(y_label_list)
3755
+ #déplacement au début du buffer
3756
+ buf.seek(0)
3757
+ #lecture du buffer et conversion en image avec PIL
3758
+ im = Image.open(buf)
3703
3759
 
3704
- ax.set_xticklabels(plt.FormatStrFormatter('%.1f').format_ticks(x_label_list), fontsize=8, rotation=30)
3705
- ax.set_yticklabels(plt.FormatStrFormatter('%.1f').format_ticks(y_label_list), fontsize=8)
3760
+ if self.palette_for_copy.values is not None:
3761
+ bufpal = io.BytesIO()
3762
+ self.palette_for_copy.export_image(bufpal,'v')
3763
+ bufpal.seek(0)
3706
3764
 
3707
- ax.set_xlabel('X [m]')
3708
- ax.set_ylabel('Y [m]')
3765
+ #lecture du buffer et conversion en image avec PIL
3766
+ impal = Image.open(bufpal)
3767
+ impal = impal.resize((int(impal.size[0]*im.size[1]*.8/impal.size[1]),int(im.size[1]*.8)))
3709
3768
 
3710
- if self.palette_for_copy.values is not None:
3711
- self.palette_for_copy.export_image(None, h_or_v='v', figax=(fig,axes[1]))
3712
- else:
3713
- axes[1].clear()
3714
- axes[1].axis('off')
3769
+ imnew = Image.new('RGB',(im.size[0]+impal.size[0], im.size[1]), (255,255,255))
3715
3770
 
3716
- # if self.active_array is not None:
3717
- # self.active_array.mypal.export_image(None, h_or_v='v', figax=(fig,axes[1]))
3718
- # elif self.active_res2d is not None:
3719
- # self.active_res2d.mypal.export_image(None, h_or_v='v', figax=(fig,axes[1]))
3771
+ # On colle l'image du buffer et la palette pour ne former qu'une seul image à copier dans le clipboard
3772
+ imnew.paste(im.convert('RGB'),(0,0))
3773
+ imnew.paste(impal.convert('RGB'),(im.size[0]-10, int((im.size[1]-impal.size[1])/3)))
3774
+ im=imnew
3775
+ bufpal.close()
3776
+ else:
3777
+ imnew = Image.new('RGB', (im.size[0], im.size[1]), (255,255,255))
3720
3778
 
3721
- # self.Paint()
3779
+ # On colle l'image du buffer et la palette pour ne former qu'une seul image à copier dans le clipboard
3780
+ imnew.paste(im.convert('RGB'),(0,0))
3781
+ im=imnew
3722
3782
 
3723
- if add_title:
3724
- ax.set_title(self.viewer_name)
3725
- fig.set_size_inches(12, 10)
3726
- fig.tight_layout()
3783
+ im.save(fn, dpi=(dpi, dpi))
3784
+ fig.set_visible(False)
3785
+ buf.close()
3727
3786
 
3728
- fig.savefig(fn, dpi=dpi)
3729
3787
  else:
3788
+ metadata = PngInfo()
3789
+ metadata.add_text('xmin', str(self.xmin))
3790
+ metadata.add_text('ymin', str(self.ymin))
3791
+ metadata.add_text('xmax', str(self.xmax))
3792
+ metadata.add_text('ymax', str(self.ymax))
3793
+
3794
+ myimage = self.get_canvas_as_image()
3730
3795
  myimage.save(fn, pnginfo=metadata)
3731
3796
 
3732
3797
  return fn, ds
@@ -4848,258 +4913,589 @@ class WolfMapViewer(wx.Frame):
4848
4913
  """
4849
4914
  curdir = Path(os.getcwd())
4850
4915
 
4916
+ real_ids = {}
4917
+
4851
4918
  myproject = Wolf_Param(None, filename=fn, toShow=False)
4852
4919
 
4853
- mykeys = ['cross_sections', 'vector', 'array']
4920
+ def check_params(myproject, curgroup) -> bool:
4854
4921
 
4855
- if 'which' in myproject.myparams.keys():
4856
- which = myproject.myparams['which']['action'][key_Param.VALUE]
4857
- if which == 'compare':
4858
- ListCompare = []
4859
- if 'array' in myproject.myparams.keys():
4860
- for curid, curname in zip(myproject.myparams['array'].keys(), myproject.myparams['array'].values()):
4861
- ListCompare.append(WolfArray(normpath(curname[key_Param.VALUE])))
4922
+ check = True
4923
+ pot_keys = list(PROJECT_GROUP_KEYS[curgroup].keys())
4862
4924
 
4863
- self.set_compare(ListCompare)
4864
- return
4925
+ for curkey in pot_keys:
4926
+ if 'mandatory' in PROJECT_GROUP_KEYS[curgroup][curkey]:
4927
+ if not myproject.is_in(curgroup, curkey):
4928
+ logging.warning(_('Missing key : ')+ curkey)
4929
+ check = False
4930
+ return check
4931
+
4932
+ def sanit_id(id:str, drawtype:draw_type) -> str:
4933
+ existing_id = self.get_list_keys(drawtype, None)
4934
+
4935
+ while id in existing_id:
4936
+ logging.warning(_('ID already exists - Changing it...'))
4937
+ id = id + '_'
4938
+
4939
+ return id
4940
+
4941
+ # COMPLEX ACTIONS
4942
+ curgroup = PROJECT_ACTION
4943
+ if myproject.is_in(curgroup):
4865
4944
 
4866
- if 'cross_sections' in myproject.myparams.keys():
4867
- for curid, curname in zip(myproject.myparams['cross_sections'].keys(),
4868
- myproject.myparams['cross_sections'].values()):
4869
- if curid != 'format' and curid != 'dirlaz':
4870
- mycs = crosssections(curname[key_Param.VALUE],
4871
- format=myproject.myparams['cross_sections']['format'][key_Param.VALUE],
4872
- dirlaz=myproject.myparams['cross_sections']['dirlaz'][key_Param.VALUE],
4873
- mapviewer = self)
4945
+ pot_keys = list(PROJECT_GROUP_KEYS[curgroup].keys())
4874
4946
 
4875
- self.add_object('cross_sections', newobj=mycs, id=curid)
4947
+ for curkey in pot_keys:
4948
+ which = myproject[(curgroup, curkey)]
4876
4949
 
4950
+ pot_val = list(PROJECT_GROUP_KEYS[curgroup][curkey].keys())
4877
4951
 
4878
- if myproject.get_group('tiles') is not None:
4952
+ if which in pot_val:
4953
+ if which == 'compare_arrays':
4879
4954
 
4880
- curid = myproject.get_param('tiles', 'id')
4881
- curfile = myproject.get_param('tiles', 'tiles_file')
4882
- curdatadir = myproject.get_param('tiles', 'data_dir')
4883
- curcompdir = myproject.get_param('tiles', 'comp_dir')
4955
+ # Comparaison de plusieurs matrices
4884
4956
 
4885
- if exists(curfile):
4886
- mytiles = Tiles(filename= curfile, parent=self, linked_data_dir=curdatadir)
4887
- mytiles.set_comp_dir(curcompdir)
4888
- self.add_object('tiles', newobj=mytiles, id=curid)
4957
+ logging.info(_('Compare action - Searching for arrays to compare...'))
4958
+ ListCompare = []
4959
+ if myproject.is_in('array'):
4960
+ for curval in myproject.get_group('array').values():
4961
+ curid = curval[key_Param.NAME]
4962
+ logging.info(_('Array to compare : ')+ curid)
4963
+ ListCompare.append(WolfArray(Path(myproject[('array', curid)])))
4964
+ else:
4965
+ logging.warning(_('No array to compare - Aborting !'))
4966
+ return
4967
+
4968
+ logging.info(_('Setting compare...'))
4969
+ self.set_compare(ListCompare)
4970
+ logging.info(_('Compare set !'))
4971
+ return
4972
+ else:
4973
+ logging.error(_('Bad parameter in project file - action : ')+ which)
4974
+
4975
+ # CROSS SECTIONS
4976
+ curgroup = PROJECT_CS
4977
+ if myproject.is_in(curgroup):
4978
+ if check_params(myproject, curgroup):
4979
+ for curval in myproject.get_group(curgroup).values():
4980
+ curid = curval[key_Param.NAME]
4981
+ if curid != 'format' and curid != 'dirlaz':
4982
+ mycs = crosssections(myproject[(curgroup, curid)],
4983
+ format = myproject[(curgroup, 'format')],
4984
+ dirlaz = myproject[(curgroup, 'dirlaz')],
4985
+ mapviewer = self)
4986
+
4987
+ locid = real_ids[(draw_type.VECTORS, curid)] = sanit_id(curid, draw_type.VECTORS)
4988
+
4989
+ self.add_object(curgroup, newobj=mycs, id=locid)
4889
4990
  else:
4890
- logging.info(_('Bad parameter in project file - tiles : ')+ curfile)
4991
+ logging.warning(_('Bad parameter in project file - cross_sections'))
4992
+
4993
+ # TILES
4994
+ curgroup = PROJECT_TILES
4995
+ if myproject.is_in(curgroup):
4996
+ if check_params(myproject, curgroup):
4997
+ curid = myproject.get_param(curgroup, 'id')
4998
+ curfile = myproject.get_param(curgroup, 'tiles_file')
4999
+ curdatadir = myproject.get_param(curgroup, 'data_dir')
5000
+ curcompdir = myproject.get_param(curgroup, 'comp_dir')
5001
+
5002
+ if exists(curfile):
5003
+ try:
5004
+ mytiles = Tiles(filename= curfile, parent=self, linked_data_dir=curdatadir)
5005
+ mytiles.set_comp_dir(curcompdir)
4891
5006
 
4892
- if myproject.get_group('laz_grid') is not None:
5007
+ locid = real_ids[(draw_type.TILES, curid)] = sanit_id(curid, draw_type.TILES)
5008
+ self.add_object(curgroup, newobj=mytiles, id=locid)
5009
+ except Exception as e:
5010
+ logging.error(_('Error in tiles import : ')+ str(e))
5011
+ else:
5012
+ logging.warning(_('File does not exist : ')+ curfile)
5013
+ else:
5014
+ logging.warning(_('Bad parameter in project file - tiles'))
4893
5015
 
4894
- curdatadir = myproject.get_param('laz_grid', 'data_dir')
5016
+ # LAZ GRID
5017
+ curgroup = PROJECT_LAZ
5018
+ if myproject.is_in(curgroup):
5019
+ if check_params(myproject, curgroup):
5020
+ try:
5021
+ self.init_laz_from_gridinfos(myproject[curgroup, 'data_dir'], myproject[(curgroup, 'classification')])
5022
+ except Exception as e:
5023
+ logging.error(_('Error in laz_grid import : ')+ str(e))
5024
+ else:
5025
+ logging.warning(_('Bad parameter in project file - laz_grid'))
5026
+
5027
+ # VECTOR DATA
5028
+ curgroup = PROJECT_VECTOR
5029
+ if myproject.is_in(curgroup):
5030
+ if check_params(myproject, curgroup):
5031
+ for curval in myproject.get_group(curgroup).values():
5032
+ curid = curval[key_Param.NAME]
5033
+ name = curval[key_Param.VALUE]
5034
+ if exists(name):
5035
+ try:
5036
+ myvec = Zones(name, parent = self, mapviewer = self)
5037
+
5038
+ locid = real_ids[(draw_type.VECTORS, curid)] = sanit_id(curid, draw_type.VECTORS)
5039
+ self.add_object(curgroup, newobj = myvec, id = locid)
5040
+ except Exception as e:
5041
+ logging.error(_('Error in vector import : ')+ str(e))
5042
+ else:
5043
+ logging.info(_('File does not exist : ') + name)
5044
+ else:
5045
+ logging.warning(_('Bad parameter in project file - vector'))
5046
+
5047
+ # ARRAY DATA
5048
+ curgroup = PROJECT_ARRAY
5049
+ if myproject.is_in(curgroup):
5050
+ if check_params(myproject, curgroup):
5051
+ for curval in myproject.get_group(curgroup).values():
5052
+ curid = curval[key_Param.NAME]
5053
+ name = curdir / Path(curval[key_Param.VALUE])
5054
+ if exists(name):
5055
+ try:
5056
+ curarray = WolfArray(name, mapviewer = self)
5057
+
5058
+ locid = real_ids[(draw_type.ARRAYS, curid)] = sanit_id(curid, draw_type.ARRAYS)
5059
+ self.add_object('array', newobj=curarray, id = locid)
5060
+ except Exception as e:
5061
+ logging.error(_('Error in array import : ')+ str(e))
5062
+ else:
5063
+ logging.info(_('File does not exist : ') + name)
5064
+ else:
5065
+ logging.warning(_('Bad parameter in project file - array'))
5066
+
5067
+ # CLOUD DATA
5068
+ curgroup = PROJECT_CLOUD
5069
+ if myproject.is_in(curgroup):
5070
+ if check_params(myproject, curgroup):
5071
+ for curval in myproject.get_group(curgroup).values():
5072
+ curid = curval[key_Param.NAME]
5073
+ name = curval[key_Param.VALUE]
5074
+ if exists(name):
5075
+ try:
5076
+ mycloud = cloud_vertices(name, mapviewer = self)
5077
+
5078
+ locid = real_ids[(draw_type.CLOUD, curid)] = sanit_id(curid, draw_type.CLOUD)
5079
+ self.add_object('cloud', newobj = mycloud, id = locid)
5080
+ except Exception as e:
5081
+ logging.error(_('Error in cloud import : ') + str(e))
5082
+ else:
5083
+ logging.info(_('File does not exist : ') + name)
5084
+ else:
5085
+ logging.warning(_('Bad parameter in project file - cloud'))
5086
+
5087
+ # 2D RESULTS
5088
+
5089
+ # CPU code
5090
+ curgroup = PROJECT_WOLF2D
5091
+ if myproject.is_in(curgroup):
5092
+ if check_params(myproject, curgroup):
5093
+ for curval in myproject.get_group(curgroup).values():
5094
+ curid = curval[key_Param.NAME]
5095
+ simdir = Path(curval[key_Param.VALUE])
5096
+ if simdir.exists():
5097
+ try:
5098
+ curwolf = Wolfresults_2D(simdir, mapviewer = self)
5099
+
5100
+ locid = real_ids[(draw_type.RES2D, curid)] = sanit_id(curid, draw_type.RES2D)
5101
+ self.add_object('res2d', newobj = curwolf, id = locid)
5102
+ except Exception as e:
5103
+ logging.error(_('Error in wolf2d import : ')+ str(e))
5104
+ else:
5105
+ logging.info(_('Directory does not exist ')) + simdir
5106
+
5107
+ self.menu_wolf2d()
5108
+ else:
5109
+ logging.warning(_('Bad parameter in project file - wolf2d'))
5110
+
5111
+ # GPU code
5112
+ curgroup = PROJECT_GPU2D
5113
+ if myproject.is_in(curgroup):
5114
+ if check_params(myproject, curgroup):
5115
+
5116
+ pgbar = wx.ProgressDialog(_('Loading GPU results'), _('Loading GPU results'), maximum=len(myproject.myparams[curgroup].keys()), parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
5117
+
5118
+ for curval in myproject.get_group(curgroup).values():
5119
+ curid = curval[key_Param.NAME]
5120
+ simdir = Path(curval[key_Param.VALUE])
5121
+ if simdir.exists():
5122
+ try:
5123
+ curwolf = wolfres2DGPU(curdir / simdir, mapviewer = self)
5124
+
5125
+ locid = real_ids[(draw_type.RES2D, curid)] = sanit_id(curid, draw_type.RES2D)
5126
+ self.add_object('res2d', newobj = curwolf, id = locid)
5127
+ except Exception as e:
5128
+ logging.error(_('Error in gpu2d import : ')+ str(e))
5129
+ else:
5130
+ logging.info(_('Bad directory : ') + simdir)
5131
+
5132
+ pgbar.Update(pgbar.GetValue() + 1)
5133
+
5134
+ pgbar.Destroy()
4895
5135
 
4896
- self.init_laz_from_gridinfos(curdatadir)
5136
+ self.menu_wolf2d()
5137
+ self.menu_2dgpu()
5138
+ else:
5139
+ logging.warning(_('Bad parameter in project file - gpu2d'))
5140
+
5141
+ # PALETTE/COLORMAP
5142
+ curgroup = PROJECT_PALETTE
5143
+ if myproject.is_in(curgroup):
5144
+ if check_params(myproject, curgroup):
5145
+ self.project_pal = {}
5146
+ for curval in myproject.get_group(curgroup).values():
5147
+ curid = curval[key_Param.NAME]
5148
+ name = Path(curval[key_Param.VALUE])
5149
+ if name.exists():
5150
+ if name.suffix == '.pal':
5151
+ mypal = wolfpalette(None, '')
5152
+ mypal.readfile(name)
5153
+ mypal.automatic = False
5154
+
5155
+ self.project_pal[curid] = mypal
5156
+ else:
5157
+ logging.warning(_('Bad palette file : ')+ name)
5158
+ else:
5159
+ logging.info(_('Bad parameter in project file - palette : ')+ name)
5160
+ else:
5161
+ logging.warning(_('Bad parameter in project file - palette'))
4897
5162
 
4898
- if 'vector' in myproject.myparams.keys():
4899
- for curid, curname in zip(myproject.myparams['vector'].keys(), myproject.myparams['vector'].values()):
4900
- if exists(curname[key_Param.VALUE]):
4901
- myvec = Zones(curname[key_Param.VALUE], parent=self, mapviewer = self)
4902
- self.add_object('vector', newobj=myvec, id=curid)
5163
+ # LINKS
5164
+ curgroup = PROJECT_PALETTE_ARRAY
5165
+ if myproject.is_in(curgroup):
5166
+ if check_params(myproject, curgroup):
5167
+ curarray: WolfArray
5168
+ if self.project_pal is not None:
5169
+
5170
+ for curval in myproject.get_group(curgroup).keys():
5171
+ id_array = curval[key_Param.NAME]
5172
+ id_pal = curval[key_Param.VALUE]
5173
+ if id_pal in self.project_pal.keys():
5174
+ try:
5175
+ curarray = self.getobj_from_id(real_ids[(draw_type.ARRAYS, id_array)])
5176
+ if curarray is not None:
5177
+ mypal:wolfpalette
5178
+ mypal = self.project_pal[id_pal]
5179
+ curarray.mypal = mypal
5180
+ if mypal.automatic:
5181
+ curarray.myops.palauto.SetValue(1)
5182
+ else:
5183
+ curarray.myops.palauto.SetValue(0)
5184
+ curarray.updatepalette(0)
5185
+ curarray.reset_plot()
5186
+ else:
5187
+ logging.warning(_('Bad parameter in project file - palette-array : ')+ id_array)
5188
+ except Exception as e:
5189
+ logging.error(_('Error in palette-array link : ')+ str(e))
5190
+ else:
5191
+ logging.warning(_('Bad parameter in project file - palette-array : ')+ id_pal)
4903
5192
  else:
4904
- logging.info(_('Bad parameter in project file - vector : ')+ curname[key_Param.VALUE])
5193
+ logging.warning(_('No palettes found in project file ! -- Add palette group in the .proj'))
5194
+ else:
5195
+ logging.warning(_('Bad parameter in project file - palette-array'))
5196
+
5197
+ curgroup = PROJECT_LINK_CS
5198
+ if myproject.is_in(curgroup):
5199
+ if self.active_cs is not None:
5200
+ if check_params(myproject, curgroup):
5201
+
5202
+ idx = real_ids[(draw_type.VECTORS, myproject[(curgroup, 'linkzones')])]
5203
+ curzones = self.get_obj_from_id(idx, draw_type.VECTORS)
5204
+
5205
+ if curzones is not None:
5206
+ self.active_cs.link_external_zones(curzones)
5207
+
5208
+ zonename = myproject[(curgroup, 'sortzone')]
5209
+ vecname = myproject[(curgroup, 'sortname')]
5210
+ downfirst = myproject[(curgroup, 'downfirst')]
5211
+
5212
+ downfirst = False
5213
+ if downfirst == 1 or str(downfirst).lower() == 'true':
5214
+ downfirst = True
5215
+
5216
+ if zonename != '' and vecname != '':
5217
+ curvec = curzones[(zonename, vecname)]
5218
+ if curvec is not None:
5219
+ try:
5220
+ self.active_cs.sort_along(curvec.asshapely_ls(), curvec.myname, downfirst)
5221
+ except Exception as e:
5222
+ logging.error(_('Error in cross_sections_link sorting : ')+ str(e))
5223
+ else:
5224
+ logging.warning(_('Bad id for sorting vector in project file - cross_sections_link'))
5225
+ else:
5226
+ logging.warning(_('Bad parameter in project file - cross_sections_link'))
5227
+ else:
5228
+ logging.warning(_('No active cross section to link !'))
5229
+
5230
+ curgroup = PROJECT_LINK_VEC_ARRAY
5231
+ # Useful to mask data outside of the linked contour
5232
+ if myproject.is_in(curgroup):
5233
+ if check_params(myproject, curgroup):
5234
+ for curval in myproject.get_group(curgroup).keys():
5235
+
5236
+ id_array = real_ids[(draw_type.ARRAYS, curval[key_Param.NAME])]
5237
+ id_zones = real_ids[(draw_type.VECTORS, curval[key_Param.VALUE])]
5238
+
5239
+ locarray:WolfArray
5240
+ locvec:Zones
5241
+
5242
+ locarray = self.get_obj_from_id(id_array, draw_type.ARRAYS)
5243
+ if locarray is None:
5244
+ locarray = self.get_obj_from_id(id_array, draw_type.RES2D)
5245
+
5246
+ locvec = self.get_obj_from_id(id_zones, draw_type.VECTORS)
5247
+
5248
+ if locvec is not None and locarray is not None:
5249
+ try:
5250
+ if locvec.nbzones == 1:
5251
+ if locvec.myzones[0].nbvectors == 1:
5252
+ locarray.linkedvec = locvec.myzones[0].myvectors[0]
5253
+ else:
5254
+ logging.warning(_('In vec-array association, You must have only 1 zone and 1 polyline !'))
5255
+ else:
5256
+ logging.warning(_('In vec-array association, You must have only 1 zone and 1 polyline !'))
5257
+
5258
+ except Exception as e:
5259
+ logging.error(_('Error in vector_array_link : ')+ str(e))
5260
+ else:
5261
+ logging.warning(_('Bad vec-array association in project file !'))
5262
+ else:
5263
+ logging.warning(_('Bad parameter in project file - vector_array_link'))
5264
+
5265
+ def save_project(self, fn, absolute:bool = True):
5266
+ """ Save project file """
5267
+
5268
+ dirproj = Path(fn).parent
5269
+
5270
+ def new_path(drawtype:draw_type, id:str) -> str:
5271
+ logging.info(_('Empty path but I need a path !'))
5272
+
5273
+ path = ''
5274
+
5275
+ ext = 'All files (*.*)|*.*'
5276
+ if drawtype == draw_type.ARRAYS:
5277
+ ext += '|Binary files (*.bin)|*.bin|Tiff files (*.tif)|*.tif|Numpy files (*.npy)|*.npy'
5278
+ elif drawtype == draw_type.VECTORS:
5279
+ ext += '|VecZ files (*.vecz)|*.vecz|Vec files (*.vec)|*.vec'
5280
+ elif drawtype == draw_type.CLOUD:
5281
+ ext += '|Cloud files (*.xyz)|*.xyz'
5282
+
5283
+ dlg = wx.FileDialog(None, _('Choose a filename for ') + id, str(dirproj), '', ext, wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
5284
+ ret = dlg.ShowModal()
5285
+
5286
+ if ret == wx.ID_OK:
5287
+ path = Path(dlg.GetPath())
5288
+
5289
+ return path
5290
+
5291
+ def sanit_path(path:Path, absolute:bool, drawtype:draw_type) -> str:
5292
+
5293
+ path = Path(path)
5294
+
5295
+ if not path.exists():
5296
+ logging.info(_('Path does not exist : ')+ str(path))
5297
+
5298
+ if absolute:
5299
+ return str(path)
5300
+ else:
5301
+ try:
5302
+ return os.path.relpath(path, dirproj)
5303
+ except:
5304
+ logging.error(_('Error in relative path : ')+ str(path) + " - " + str(dirproj))
5305
+ logging.info(_('Returning absolute path instead !'))
5306
+ return str(path.absolute())
5307
+
5308
+ myproject = Wolf_Param(None, toShow=False, to_read=False, filename=fn, init_GUI=False)
5309
+
5310
+ # matrices
5311
+ try:
5312
+ curgroup = PROJECT_ARRAY
5313
+ for curel in self.iterator_over_objects(draw_type.ARRAYS):
5314
+ curel:WolfArray
5315
+ if curel.filename == '':
5316
+ newpath = new_path(draw_type.ARRAYS, curel.idx)
5317
+ if newpath == '':
5318
+ logging.warning(_('No path for array : ')+ curel.idx + _(' - Ignoring it !'))
5319
+ continue
5320
+ curel.write_all(newpath)
5321
+
5322
+ curpath = sanit_path(curel.filename, absolute, draw_type.ARRAYS)
5323
+
5324
+ myproject.add_param(curgroup, curel.idx, curpath)
5325
+ except:
5326
+ logging.error(_('Error in saving arrays'))
5327
+
5328
+ # résultats 2D
5329
+ try:
5330
+ curgroup = PROJECT_WOLF2D
5331
+ for curel in self.iterator_over_objects(draw_type.RES2D):
5332
+ if type(curel) == Wolfresults_2D:
5333
+ myproject.add_param(curgroup, curel.idx, sanit_path(curel.filename, absolute, draw_type.RES2D))
5334
+
5335
+ curgroup = PROJECT_GPU2D
5336
+ for curel in self.iterator_over_objects(draw_type.RES2D):
5337
+ if type(curel) == wolfres2DGPU:
5338
+ myproject.add_param(curgroup, curel.idx, sanit_path(curel.filename, absolute, draw_type.RES2D))
5339
+ except:
5340
+ logging.error(_('Error in saving 2D results'))
5341
+
5342
+ # vecteurs
5343
+ try:
5344
+ curgroup = PROJECT_VECTOR
5345
+ for curel in self.iterator_over_objects(draw_type.VECTORS):
5346
+ if isinstance(curel, crosssections):
5347
+ continue
4905
5348
 
4906
- if 'array' in myproject.myparams.keys():
4907
- for curid, curname in zip(myproject.myparams['array'].keys(), myproject.myparams['array'].values()):
5349
+ curel:Zones
5350
+ if curel.filename == '':
5351
+ newpath = new_path(draw_type.VECTORS, curel.idx)
5352
+ if newpath == '':
5353
+ logging.warning(_('No path for vector : ')+ curel.idx + _(' - Ignoring it !'))
5354
+ continue
5355
+ curel.saveas(newpath)
4908
5356
 
4909
- if exists(curname[key_Param.VALUE]):
4910
- curarray = WolfArray(curname[key_Param.VALUE], mapviewer=self)
4911
- self.add_object('array', newobj=curarray, id=curid)
4912
- else:
4913
- logging.info(_('Bad parameter in project file - array : ')+ curname[key_Param.VALUE])
5357
+ myproject.add_param(curgroup, curel.idx, sanit_path(curel.filename, absolute, draw_type.VECTORS))
5358
+ except:
5359
+ logging.error(_('Error in saving vectors'))
4914
5360
 
4915
- if 'cloud' in myproject.myparams.keys():
4916
- for curid, curname in zip(myproject.myparams['cloud'].keys(), myproject.myparams['cloud'].values()):
4917
- if exists(curname[key_Param.VALUE]):
4918
- mycloud = cloud_vertices(curname[key_Param.VALUE], mapviewer=self)
4919
- self.add_object('cloud', newobj=mycloud, id=curid)
4920
- else:
4921
- logging.info(_('Bad parameter in project file - cloud : ')+ curname[key_Param.VALUE])
5361
+ # cross sections
5362
+ try:
5363
+ curgroup = PROJECT_CS
5364
+ for curel in self.iterator_over_objects(draw_type.VECTORS):
5365
+ if isinstance(curel, crosssections):
5366
+ myproject.add_param(curgroup, curel.idx, sanit_path(curel.filename, absolute, draw_type.VECTORS))
5367
+ except:
5368
+ logging.error(_('Error in saving cross sections'))
4922
5369
 
4923
- if 'wolf2d' in myproject.myparams.keys():
4924
- for curid, curname in zip(myproject.myparams['wolf2d'].keys(), myproject.myparams['wolf2d'].values()):
4925
- if exists(curname[key_Param.VALUE]):
4926
- curwolf = Wolfresults_2D(curname[key_Param.VALUE], mapviewer=self)
4927
- self.add_object('res2d', newobj=curwolf, id=curid)
4928
- else:
4929
- logging.info(_('Bad parameter in project file - wolf2d : ')+ curname[key_Param.VALUE])
5370
+ # nuages de points
5371
+ try:
5372
+ curgroup = PROJECT_CLOUD
5373
+ for curel in self.iterator_over_objects(draw_type.CLOUD):
5374
+ myproject.add_param(curgroup, curel.idx, sanit_path(curel.filename, absolute, draw_type.CLOUD))
5375
+ except:
5376
+ logging.error(_('Error in saving clouds'))
4930
5377
 
4931
- self.menu_wolf2d()
5378
+ # palettes
5379
+ try:
5380
+ if self.project_pal is not None:
5381
+ curgroup = PROJECT_PALETTE
5382
+ for curel in self.project_pal.keys():
5383
+ myproject.add_param(curgroup, curel, sanit_path(self.project_pal[curel].filename, absolute, draw_type.OTHER))
5384
+ except:
5385
+ logging.error(_('Error in saving palettes'))
4932
5386
 
4933
- if 'gpu2d' in myproject.myparams.keys():
5387
+ # tiles
5388
+ try:
5389
+ curgroup = PROJECT_TILES
5390
+ for curel in self.iterator_over_objects(draw_type.TILES):
5391
+ myproject.add_param(curgroup, curel.idx, sanit_path(curel.filename, absolute, draw_type.OTHER))
5392
+ myproject.add_param(curgroup, 'data_dir', sanit_path(curel.linked_data_dir, absolute, draw_type.OTHER))
5393
+ myproject.add_param(curgroup, 'comp_dir', sanit_path(curel.linked_data_dir_comp, absolute, draw_type.OTHER))
5394
+ except:
5395
+ logging.error(_('Error in saving tiles'))
4934
5396
 
4935
- pgbar = wx.ProgressDialog(_('Loading GPU results'), _('Loading GPU results'), maximum=len(myproject.myparams['gpu2d'].keys()), parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
5397
+ # LAZ GRID
5398
+ try:
5399
+ if self.mylazgrid is not None:
5400
+ curgroup = PROJECT_LAZ
5401
+ myproject.add_param(curgroup, 'data_dir', sanit_path(self.mylazgrid.dir, absolute, draw_type.OTHER))
5402
+ myproject.add_param(curgroup, 'classification', self.mylazgrid.colors.class_name)
5403
+ except:
5404
+ logging.error(_('Error in saving laz grid'))
4936
5405
 
4937
- for curid, curname in zip(myproject.myparams['gpu2d'].keys(), myproject.myparams['gpu2d'].values()):
4938
- if exists(curname[key_Param.VALUE]):
5406
+ myproject.Save(fn)
4939
5407
 
4940
- if 'simul_gpu_results' in curname[key_Param.VALUE]:
4941
- curwolf = wolfres2DGPU(curdir / Path(curname[key_Param.VALUE]), mapviewer=self)
4942
- else:
4943
- if exists(join(curname[key_Param.VALUE], 'simul_gpu_results')):
4944
- curwolf = wolfres2DGPU(curdir / Path(join(curname[key_Param.VALUE], 'simul_gpu_results')), mapviewer=self)
4945
- else:
4946
- logging.info(_('Bad directory : ')+ curname[key_Param.VALUE])
4947
5408
 
4948
- self.add_object('res2d', newobj=curwolf, id=curid)
4949
- else:
4950
- logging.info(_('Bad directory : ')+ curname[key_Param.VALUE])
5409
+ def help_project(self):
5410
+ """ Help for project file.
4951
5411
 
4952
- pgbar.Update(pgbar.GetValue() + 1)
5412
+ Define which elements can be saved in a project file.
4953
5413
 
4954
- pgbar.Destroy()
5414
+ """
4955
5415
 
4956
- self.menu_wolf2d()
4957
- self.menu_2dgpu()
5416
+ logging.info(_('Project file help'))
4958
5417
 
4959
- if 'palette' in myproject.myparams.keys():
4960
- self.project_pal = {}
4961
- for curid, curname in zip(myproject.myparams['palette'].keys(), myproject.myparams['palette'].values()):
4962
- if exists(curname[key_Param.VALUE]):
4963
- mypal = wolfpalette(None, '')
4964
- mypal.readfile(curname[key_Param.VALUE])
4965
- mypal.automatic = False
5418
+ logging.info(_('Project file is a file containing some information about the current project.'))
4966
5419
 
4967
- self.project_pal[curid] = mypal
4968
- else:
4969
- logging.info(_('Bad parameter in project file - palette : ')+ curname[key_Param.VALUE])
5420
+ logging.info(_('It can contain the following informations :'))
4970
5421
 
4971
- if 'palette-array' in myproject.myparams.keys():
4972
- curarray: WolfArray
4973
- if self.project_pal is not None:
4974
- for curid, curname in zip(myproject.myparams['palette-array'].keys(),
4975
- myproject.myparams['palette-array'].values()):
4976
- if curname[key_Param.VALUE] in self.project_pal.keys():
4977
- curarray = self.getobj_from_id(curid)
4978
- if curarray is not None:
4979
- mypal:wolfpalette
4980
- mypal = self.project_pal[curname[key_Param.VALUE]]
4981
- curarray.mypal = mypal
4982
- if mypal.automatic:
4983
- curarray.myops.palauto.SetValue(1)
4984
- else:
4985
- curarray.myops.palauto.SetValue(0)
4986
- curarray.updatepalette(0)
4987
- curarray.delete_lists()
4988
- else:
4989
- logging.warning(_('Bad parameter in project file - palette-array : ')+ curid)
5422
+ logging.info(_(' - Arrays :'))
5423
+ logging.info(_(' - id'))
5424
+ logging.info(_(' - filename in relative or absolute path'))
4990
5425
 
4991
- if 'cross_sections_link' in myproject.myparams.keys():
4992
- if 'linkzones' in myproject.myparams['cross_sections_link'].keys():
4993
- idx = myproject.myparams['cross_sections_link']['linkzones'][key_Param.VALUE]
5426
+ logging.info(_(' - Cross sections :'))
5427
+ logging.info(_(' - id'))
5428
+ logging.info(_(' - filename in relative or absolute path'))
4994
5429
 
4995
- for curzones in self.iterator_over_objects(draw_type.VECTORS):
4996
- curzones: Zones
4997
- if curzones.idx == idx:
4998
- self.active_cs.link_external_zones(curzones)
5430
+ logging.info(_(' - Vectors :'))
5431
+ logging.info(_(' - id'))
5432
+ logging.info(_(' - filename in relative or absolute path'))
4999
5433
 
5000
- zonename = ''
5001
- vecname = ''
5002
-
5003
- if 'sortzone' in myproject.myparams['cross_sections_link'].keys():
5004
- zonename = myproject.myparams['cross_sections_link']['sortzone'][key_Param.VALUE]
5005
- if 'sortname' in myproject.myparams['cross_sections_link'].keys():
5006
- vecname = myproject.myparams['cross_sections_link']['sortname'][key_Param.VALUE]
5007
-
5008
- if zonename != '' and vecname != '':
5009
- names = [cur.myname for cur in curzones.myzones]
5010
- idx = names.index(zonename)
5011
- curzone = curzones.myzones[idx]
5012
- names = [cur.myname for cur in curzone.myvectors]
5013
- idx = names.index(vecname)
5014
- curvec = curzone.myvectors[idx]
5015
-
5016
- if curvec is not None:
5017
- curvec: vector
5018
- self.active_cs.sort_along(curvec.asshapely_ls(), curvec.myname, False)
5019
-
5020
- if 'vector_array_link' in myproject.myparams.keys():
5021
- for curid, curname in zip(myproject.myparams['vector_array_link'].keys(), myproject.myparams['vector_array_link'].values()):
5022
-
5023
- locvec = None
5024
- locarray = None
5025
- for curvec in self.myvectors:
5026
- if curvec.idx == curname[key_Param.VALUE].lower():
5027
- locvec=curvec
5028
- break
5434
+ logging.info(_(' - Clouds :'))
5435
+ logging.info(_(' - id'))
5436
+ logging.info(_(' - filename in relative or absolute path'))
5029
5437
 
5030
- for curarray in self.myarrays:
5031
- if curarray.idx == curid.lower():
5032
- locarray=curarray
5033
- break
5438
+ logging.info(_(' - Tiles :'))
5439
+ logging.info(_(' - id'))
5440
+ logging.info(_(' - filename in relative or absolute path'))
5034
5441
 
5035
- if locvec is not None and locarray is not None:
5442
+ logging.info(_(' - LAZ grid :'))
5443
+ logging.info(_(' - data_dir : directory containing the NUMPY grid'))
5444
+ logging.info(_(' - classification : classification of the laz files'))
5036
5445
 
5037
- locarray.linkedvec = locvec.myzones[0].myvectors[0]
5446
+ logging.info(_(' - Palettes :'))
5447
+ logging.info(_(' - id'))
5448
+ logging.info(_(' - filename in relative or absolute path'))
5038
5449
 
5039
- else:
5450
+ logging.info(_(' - Wolf2D CPU results :'))
5451
+ logging.info(_(' - id'))
5452
+ logging.info(_(' - filename in relative or absolute path'))
5040
5453
 
5041
- logging.warning(_('Bad vec-array association in project file !'))
5042
- logging.warning(curid)
5043
- logging.warning(curname[key_Param.VALUE])
5454
+ logging.info(_(' - Wolf2D GPU results :'))
5455
+ logging.info(_(' - id'))
5456
+ logging.info(_(' - filename in relative or absolute path'))
5044
5457
 
5045
- def save_project(self, fn):
5046
- myproject = Wolf_Param(None, toShow=False)
5458
+ logging.info(_(' - Palette-Array links :'))
5459
+ logging.info(_(' - id of the array'))
5460
+ logging.info(_(' - id of the palette'))
5047
5461
 
5048
- mykeys = ['cross_sections', 'vector', 'array', 'wolf2d']
5049
- for curkey in mykeys:
5050
- myproject[curkey] = {}
5051
- """
5052
- # myproject.myparams['which']={}
5053
- # myproject.myparams['which']['action']={}
5054
- # myproject.myparams['which']['action'][key_Param.VALUE]
5055
-
5056
- # mycs = self.active_cs
5057
- # if mycs is not None:
5058
- # myproject.myparams['cross_sections']={}
5059
- # myproject.myparams['cross_sections']['mycs']={}
5060
- # myproject.myparams['cross_sections']['mycs'][key_Param.VALUE]=mycs.filename
5061
-
5062
- # myproject.myparams['vector']={}
5063
- # myproject.myparams['vector']['river']={}
5064
- ## myproject.myparams['vector']['river'][key_Param.VALUE]=self.added[draw_type.VECTORS.value][0].filename
5065
-
5066
- # if 'array' in myproject.myparams.key():
5067
- # for curid,curname in zip(myproject.myparams['array'].keys(),myproject.myparams['array'].values()):
5068
- # curarray=WolfArray(curname[key_Param.VALUE])
5069
- # self.add_object('array',newobj=curarray,id=curid)
5070
- """
5071
- # matrices
5072
- try:
5073
- for curel in self.iterator_over_objects(draw_type.ARRAYS):
5074
- myproject['array'][curel.idx] = {}
5075
- myproject['array'][curel.idx][key_Param.VALUE] = curel.filename
5462
+ logging.info(_(' - Vector-Array links :'))
5463
+ logging.info(_(' - id of the array'))
5464
+ logging.info(_(' - id of the vector (containing only 1 zone and 1 vector)'))
5076
5465
 
5077
- except:
5078
- pass
5466
+ logging.info(_(' - Cross section links :'))
5467
+ logging.info(_(' - id of the cross section'))
5468
+ logging.info(_(' - id of the vector to sort along'))
5469
+ logging.info(_(' - id of the zone to link'))
5470
+ logging.info(_(' - downfirst : True or False'))
5079
5471
 
5080
- # résultats 2D
5081
- try:
5082
- for curel in self.iterator_over_objects(draw_type.RES2D):
5083
- myproject['wolf2d'][curel.idx] = {}
5084
- myproject['wolf2d'][curel.idx][key_Param.VALUE] = curel.filename
5472
+ logging.info('')
5473
+ logging.info(_('A tabulation is used to separate the value and the key.'))
5474
+ logging.info('')
5085
5475
 
5086
- except:
5087
- pass
5476
+ logging.info(_('Exemple :'))
5088
5477
 
5089
- # vecteurs
5090
- try:
5091
- for curel in self.iterator_over_objects(draw_type.VECTORS):
5092
- myproject['vector'][curel.idx] = {}
5093
- myproject['vector'][curel.idx][key_Param.VALUE] = curel.filename
5478
+ logging.info('')
5094
5479
 
5095
- except:
5096
- pass
5480
+ logging.info('array:')
5481
+ logging.info('myid1\tmyfilename_array1')
5482
+ logging.info('myid2\tmy../filename_array2')
5483
+ logging.info('vector:')
5484
+ logging.info('myvec1\tmy../../filename_vecz1')
5485
+ logging.info('myvec2\tmyfilename_vecz2')
5486
+ logging.info('laz_grid:')
5487
+ logging.info('data_dir\tD:\\MODREC-Vesdre\\LAZ_Vesdre\\2023\\grids_flt32')
5488
+ logging.info('classification\tSPW-Geofit 2023')
5097
5489
 
5098
5490
  def plot_laz_around_active_vec(self):
5491
+ """ Plot laz data around active vector """
5492
+
5099
5493
  if self.active_vector is None:
5494
+ logging.warning(_('Please activate a vector'))
5100
5495
  return
5101
5496
 
5102
5497
  if self.mylazgrid is None:
5498
+ logging.warning(_('No laz grid'))
5103
5499
  return
5104
5500
 
5105
5501
  dlg = wx.NumberEntryDialog(None, _('Enter the size of the window around the active vector [cm]'), _('Window size'),_('Window size'), 500, 0, 2000)
@@ -5121,11 +5517,8 @@ class WolfMapViewer(wx.Frame):
5121
5517
  s,z = copy_vec.get_sz()
5122
5518
  notmasked = np.where(z != -99999.)
5123
5519
 
5124
- fig.plot(s,z, c='black', linewidth=2.0)
5125
-
5126
- # ax.plot(s[notmasked], z[notmasked], c='black', linewidth=2.0)
5520
+ fig.plot(s[notmasked],z[notmasked], c='black', linewidth=2.0)
5127
5521
 
5128
- # fig.show()
5129
5522
 
5130
5523
  def clip_laz_gridded(self):
5131
5524
  """ Clip laz grid on current zoom """
@@ -5139,10 +5532,11 @@ class WolfMapViewer(wx.Frame):
5139
5532
 
5140
5533
  logging.info(_('Clip LAZ grid on current zoom {}-{} {}-{}').format(curbounds[0][0],curbounds[0][1],curbounds[1][0],curbounds[1][1]))
5141
5534
 
5142
- def decimate_data(self, factor:int = 10):
5535
+ def decimate_laz_data(self, factor:int = 10):
5143
5536
  """ Decimate data """
5144
5537
 
5145
5538
  if self.mylazdata is None:
5539
+ logging.warning(_('No laz data'))
5146
5540
  return
5147
5541
 
5148
5542
  self.mylazdata = self.mylazdata[::factor]
@@ -5504,7 +5898,7 @@ class WolfMapViewer(wx.Frame):
5504
5898
  for curframe in self.linkedList:
5505
5899
  curframe.mylazdata = self.mylazdata
5506
5900
 
5507
- def init_laz_from_gridinfos(self, dirlaz:str = None):
5901
+ def init_laz_from_gridinfos(self, dirlaz:str = None, classification:Literal['SPW-Geofit 2023', 'SPW 2013-2014'] = 'SPW-Geofit 2023'):
5508
5902
 
5509
5903
  if dirlaz is None:
5510
5904
  dlg = wx.DirDialog(None, _('Choose directory where LAZ data/gridinfo are stored'))
@@ -5516,19 +5910,20 @@ class WolfMapViewer(wx.Frame):
5516
5910
 
5517
5911
  self.mylazgrid = xyz_laz_grids(dirlaz)
5518
5912
 
5519
- dlg = wx.SingleChoiceDialog(None, _('Choose the classification'), _('Classification'), ['SPW-Geofit 2023', 'SPW 2013-2014'], wx.CHOICEDLG_STYLE)
5520
- ret = dlg.ShowModal()
5521
- if ret != wx.ID_OK:
5913
+ if classification not in ['SPW-Geofit 2023', 'SPW 2013-2014']:
5914
+ dlg = wx.SingleChoiceDialog(None, _('Choose the classification'), _('Classification'), ['SPW-Geofit 2023', 'SPW 2013-2014'], wx.CHOICEDLG_STYLE)
5915
+ ret = dlg.ShowModal()
5916
+ if ret != wx.ID_OK:
5917
+ dlg.Destroy()
5918
+ return
5919
+ classification = dlg.GetStringSelection()
5522
5920
  dlg.Destroy()
5523
- return
5524
5921
 
5525
- if dlg.GetStringSelection() == 'SPW 2013-2014':
5922
+ if classification == 'SPW 2013-2014':
5526
5923
  self.mylazgrid.colors.init_2013()
5527
5924
  else:
5528
5925
  self.mylazgrid.colors.init_2023()
5529
5926
 
5530
- dlg.Destroy()
5531
-
5532
5927
  if self.linked:
5533
5928
  if len(self.linkedList) > 0:
5534
5929
  for curframe in self.linkedList:
@@ -5622,7 +6017,9 @@ class WolfMapViewer(wx.Frame):
5622
6017
 
5623
6018
  self.currently_readresults = True
5624
6019
 
5625
- for curmodel in self.iterator_over_objects(draw_type.RES2D):
6020
+ pgbar = wx.ProgressDialog(_('Reading results'), _('Reading results'), maximum=len(self.myres2D), parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
6021
+
6022
+ for id, curmodel in enumerate(self.iterator_over_objects(draw_type.RES2D)):
5626
6023
  curmodel: Wolfresults_2D
5627
6024
  logging.info(_('Updating {} - Last result'.format(curmodel.idx)))
5628
6025
 
@@ -5630,6 +6027,10 @@ class WolfMapViewer(wx.Frame):
5630
6027
  curmodel.set_currentview()
5631
6028
  self._update_sim_explorer(curmodel)
5632
6029
 
6030
+ pgbar.Update(id + 1, _('Reading results') + ' - ' + curmodel.idx)
6031
+
6032
+ pgbar.Destroy()
6033
+
5633
6034
  self.Refresh()
5634
6035
  self.currently_readresults = False
5635
6036
  self._update_mytooltip()
@@ -5776,12 +6177,14 @@ class WolfMapViewer(wx.Frame):
5776
6177
 
5777
6178
  itemlabel = item.ItemLabel
5778
6179
 
5779
- autoscale = True
6180
+ autoscale = False
5780
6181
 
5781
6182
  if id == wx.ID_OPEN:
6183
+ autoscale = True
5782
6184
  filterProject = "proj (*.proj)|*.proj|param (*.param)|*.param|all (*.*)|*.*"
5783
6185
  file = wx.FileDialog(self, "Choose file", wildcard=filterProject)
5784
- if file.ShowModal() == wx.ID_CANCEL:
6186
+ ret = file.ShowModal()
6187
+ if ret == wx.ID_CANCEL:
5785
6188
  file.Destroy()
5786
6189
  return
5787
6190
  else:
@@ -5797,30 +6200,28 @@ class WolfMapViewer(wx.Frame):
5797
6200
  elif itemlabel == _('Shortcuts'):
5798
6201
  # show shortcuts in log
5799
6202
  self.print_shortcuts(True)
5800
- autoscale = False
6203
+
6204
+ elif itemlabel == _('Project .proj'):
6205
+ # show shortcuts in log
6206
+ self.help_project()
5801
6207
 
5802
6208
  elif itemlabel == _('Show logs/informations'):
5803
6209
  self.check_logging()
5804
- autoscale = False
5805
6210
 
5806
6211
  elif itemlabel == _('Show values'):
5807
6212
  self.check_tooltip()
5808
- autoscale = False
5809
6213
 
5810
6214
  elif itemlabel == _('About'):
5811
6215
  #print About Frame
5812
6216
  self.print_About()
5813
- autoscale = False
5814
6217
 
5815
6218
  elif itemlabel == _('Check for updates'):
5816
6219
  # check for new version
5817
6220
 
5818
6221
  self.check_for_updates()
5819
- autoscale = False
5820
6222
 
5821
6223
  elif itemlabel == _("Plot integrated Q along active vector..."):
5822
6224
  """ Integrate Q along active vector """
5823
- autoscale = False
5824
6225
 
5825
6226
  if self.active_vector is None:
5826
6227
  logging.warning(_('No active vector !'))
@@ -5838,7 +6239,6 @@ class WolfMapViewer(wx.Frame):
5838
6239
 
5839
6240
  elif itemlabel == _("Plot integrated Q along active zone..."):
5840
6241
  """ Integrate Q along active zone """
5841
- autoscale = False
5842
6242
 
5843
6243
  if self.active_zone is None:
5844
6244
  logging.warning(_('No active zone !'))
@@ -5851,7 +6251,6 @@ class WolfMapViewer(wx.Frame):
5851
6251
  self.active_res2d.plot_q(self.active_zone.myvectors, ['border'] * self.active_zone.nbvectors, toshow=True)
5852
6252
 
5853
6253
  elif itemlabel == _("Export integrated Q along active vector..."):
5854
- autoscale = False
5855
6254
 
5856
6255
  if self.active_vector is None:
5857
6256
  logging.warning(_('No active vector !'))
@@ -5906,7 +6305,6 @@ class WolfMapViewer(wx.Frame):
5906
6305
 
5907
6306
 
5908
6307
  elif itemlabel == _("Export integrated Q along all vectors in active zone..."):
5909
- autoscale = False
5910
6308
 
5911
6309
  if self.active_zone is None:
5912
6310
  logging.warning(_('No active zone !'))
@@ -5961,7 +6359,6 @@ class WolfMapViewer(wx.Frame):
5961
6359
 
5962
6360
 
5963
6361
  elif itemlabel == _("Plot stats unknown (selected nodes)..."):
5964
- autoscale = False
5965
6362
 
5966
6363
  if self.active_res2d is None:
5967
6364
  logging.warning(_('No active 2D result !'))
@@ -5995,7 +6392,6 @@ class WolfMapViewer(wx.Frame):
5995
6392
  fig.show()
5996
6393
 
5997
6394
  elif itemlabel == _("Plot stats unknown (inside active vector)..."):
5998
- autoscale = False
5999
6395
 
6000
6396
  if self.active_res2d is None:
6001
6397
  logging.warning(_('No active 2D result !'))
@@ -6025,7 +6421,6 @@ class WolfMapViewer(wx.Frame):
6025
6421
  fig, ax = self.active_res2d.plot_h(self.active_vector, unknown, toshow=True)
6026
6422
 
6027
6423
  elif itemlabel == _("Plot stats unknown (inside active zone)..."):
6028
- autoscale = False
6029
6424
 
6030
6425
  if self.active_res2d is None:
6031
6426
  logging.warning(_('No active 2D result !'))
@@ -6062,7 +6457,6 @@ class WolfMapViewer(wx.Frame):
6062
6457
 
6063
6458
  elif itemlabel == _("Plot active vector..."):
6064
6459
  """ Plot data along active vector """
6065
- autoscale = False
6066
6460
 
6067
6461
  if self.active_vector is None:
6068
6462
  logging.warning(_('No active vector !'))
@@ -6138,36 +6532,24 @@ class WolfMapViewer(wx.Frame):
6138
6532
  fig.canvas.flush_events()
6139
6533
 
6140
6534
  elif itemlabel == _("Compute and apply unique colormap on all..."):
6141
- autoscale = False
6142
-
6143
6535
  self.uniquecolormap()
6144
6536
 
6145
6537
  elif itemlabel == _("Load and apply unique colormap on all..."):
6146
- autoscale = False
6147
-
6148
6538
  self.uniquecolormap(True)
6149
6539
 
6150
6540
  elif itemlabel == _("Force uniform in parts on all..."):
6151
- autoscale = False
6152
6541
  self.uniforminparts_all(True)
6153
6542
 
6154
6543
  elif itemlabel == _("Force linear interpolation on all..."):
6155
- autoscale = False
6156
6544
  self.uniforminparts_all(False)
6157
6545
 
6158
6546
  elif itemlabel == _("Load and apply mask (nap)..."):
6159
- autoscale = False
6160
-
6161
6547
  self.loadnap_and_apply()
6162
6548
 
6163
6549
  elif itemlabel == _("Filter inundation arrays..."):
6164
- autoscale = False
6165
-
6166
6550
  self.filter_inundation()
6167
6551
 
6168
6552
  elif itemlabel == _("Plot active polygons..."):
6169
- autoscale = False
6170
-
6171
6553
  if self.active_zone is None:
6172
6554
  logging.warning(_('No active zone ! -- please select a zone containing polygons !'))
6173
6555
  return
@@ -6243,7 +6625,7 @@ class WolfMapViewer(wx.Frame):
6243
6625
  fig.show()
6244
6626
 
6245
6627
  elif itemlabel == _("Manage banks..."):
6246
- autoscale = False
6628
+
6247
6629
  if self.active_vector is None:
6248
6630
  msg = _('Active vector is None\nPlease activate the one desired')
6249
6631
  msg += _('\n')
@@ -6254,13 +6636,11 @@ class WolfMapViewer(wx.Frame):
6254
6636
  self.managebanks()
6255
6637
 
6256
6638
  elif itemlabel == _("Create banks from vertices..."):
6257
- autoscale = False
6258
6639
 
6259
6640
  self.active_cs.create_zone_from_banksbed()
6260
6641
  self.active_cs.linked_zones.showstructure()
6261
6642
 
6262
6643
  elif itemlabel == _("Link cross sections to active zones"):
6263
- autoscale = False
6264
6644
 
6265
6645
  if self.active_cs is None:
6266
6646
  msg = _('Active cross sections is None\nPlease activate the one desired')
@@ -6279,7 +6659,6 @@ class WolfMapViewer(wx.Frame):
6279
6659
  self.active_cs.link_external_zones(self.active_zones)
6280
6660
 
6281
6661
  elif itemlabel == _("Rename cross sections..."):
6282
- autoscale = False
6283
6662
 
6284
6663
  dlg = wx.TextEntryDialog(None, _('Which starting point?'))
6285
6664
  ret = dlg.ShowModal()
@@ -6295,15 +6674,12 @@ class WolfMapViewer(wx.Frame):
6295
6674
  # self.import_3dfaces()
6296
6675
 
6297
6676
  elif itemlabel == _("Interpolate on active triangulation..."):
6298
- autoscale = False
6299
6677
  self.interpolate_triangulation()
6300
6678
 
6301
6679
  elif itemlabel==_("Compare cloud to array..."):
6302
- autoscale = False
6303
6680
  self.compare_cloud2array()
6304
6681
 
6305
6682
  elif itemlabel==_("Split cloud..."):
6306
- autoscale = False
6307
6683
 
6308
6684
  if self.active_cloud is None:
6309
6685
  logging.warning(_('No active cloud !'))
@@ -6316,26 +6692,21 @@ class WolfMapViewer(wx.Frame):
6316
6692
  self.split_cloud_by_vector()
6317
6693
 
6318
6694
  elif itemlabel==_("Compare triangles to array..."):
6319
- autoscale = False
6320
6695
  self.compare_tri2array()
6321
6696
 
6322
6697
  elif itemlabel == _("Move triangles..."):
6323
- autoscale = False
6324
6698
  self.move_triangles()
6325
6699
 
6326
6700
  elif itemlabel == _("Rotate triangles..."):
6327
- autoscale = False
6328
6701
  self.rotate_triangles()
6329
6702
 
6330
6703
  elif itemlabel == _("Create contour from checked arrays..."):
6331
- autoscale = False
6332
6704
 
6333
6705
  # Create contour from checked arrays and add it to the list of objects
6334
6706
  newzones = self.create_Zones_from_arrays(self.get_list_objects(draw_type.ARRAYS, checked_state=True))
6335
6707
  self.add_object('vector', newobj=newzones, ToCheck=True, id='Contours from arrays')
6336
6708
 
6337
6709
  elif itemlabel == _("Calculator..."):
6338
- autoscale = False
6339
6710
 
6340
6711
  if self.calculator is None:
6341
6712
  self.calculator = Calculator(mapviewer = self)
@@ -6343,12 +6714,10 @@ class WolfMapViewer(wx.Frame):
6343
6714
  self.calculator.Show()
6344
6715
 
6345
6716
  elif itemlabel == _('Image digitizer...'):
6346
- autoscale = False
6347
6717
 
6348
6718
  new_digitizer = Digitizer()
6349
6719
 
6350
6720
  elif itemlabel == _("Memory views..."):
6351
- autoscale = False
6352
6721
 
6353
6722
  if self.memory_views is None:
6354
6723
  self.memory_views = Memory_Views()
@@ -6360,7 +6729,6 @@ class WolfMapViewer(wx.Frame):
6360
6729
  self._memory_views_gui.Show()
6361
6730
 
6362
6731
  elif itemlabel == _("Create bridge and export gltf..."):
6363
- autoscale = False
6364
6732
 
6365
6733
  if self.active_cs is None:
6366
6734
  msg = _('Active cross sections is None\nPlease activate the one desired')
@@ -6372,7 +6740,6 @@ class WolfMapViewer(wx.Frame):
6372
6740
  self.start_action('bridge gltf', _('Create bridge and export gltf...'))
6373
6741
 
6374
6742
  elif itemlabel == _("Export cross sections to gltf..."):
6375
- autoscale = False
6376
6743
 
6377
6744
  if self.active_cs is None:
6378
6745
  msg = _('Active cross sections is None\nPlease activate the one desired')
@@ -6402,21 +6769,20 @@ class WolfMapViewer(wx.Frame):
6402
6769
  self.active_cs.export_gltf(zmin, fn)
6403
6770
 
6404
6771
  elif itemlabel == _("New cloud Viewer..."):
6405
- autoscale = False
6772
+
6406
6773
  if self.myinterp is not None:
6407
6774
  self.myinterp.viewer_interpolator()
6408
6775
 
6409
6776
  elif itemlabel == _("Interpolate on active array..."):
6410
- autoscale = False
6777
+
6411
6778
  if self.myinterp is not None:
6412
6779
  self.interpolate_cs()
6413
6780
 
6414
6781
  elif itemlabel == _("Interpolate active cloud on active array..."):
6415
- autoscale = False
6416
6782
  self.interpolate_cloud()
6417
6783
 
6418
- elif itemlabel == _('Save project'):
6419
- autoscale = False
6784
+ elif itemlabel == _('Save project as...'):
6785
+
6420
6786
  filterProject = "proj (*.proj)|*.proj|param (*.param)|*.param|all (*.*)|*.*"
6421
6787
  file = wx.FileDialog(self, "Name your file", wildcard=filterProject, style=wx.FD_SAVE)
6422
6788
  if file.ShowModal() == wx.ID_CANCEL:
@@ -6427,18 +6793,21 @@ class WolfMapViewer(wx.Frame):
6427
6793
  filename = file.GetPath()
6428
6794
  file.Destroy()
6429
6795
 
6430
- self.save_project(filename)
6796
+ abspath = True
6797
+ dlg = wx.MessageDialog(None, _('Do you want to save the paths in absolute mode ?'), _('Relative paths'), style=wx.YES_NO)
6798
+ ret = dlg.ShowModal()
6799
+ if ret == wx.ID_NO:
6800
+ abspath = False
6801
+
6802
+ self.save_project(filename, absolute= abspath)
6431
6803
 
6432
6804
  elif itemlabel == _('Initialize from npz'):
6433
- autoscale=False
6434
6805
  self.init_laz_from_numpy()
6435
6806
 
6436
6807
  elif itemlabel == _('Initialize from GridInfos'):
6437
- autoscale=False
6438
6808
  self.init_laz_from_gridinfos()
6439
6809
 
6440
6810
  elif itemlabel == _('Create cloud points from bridges'):
6441
- autoscale=False
6442
6811
  if self.mylazdata is None:
6443
6812
  self.init_laz_from_numpy()
6444
6813
 
@@ -6457,7 +6826,7 @@ class WolfMapViewer(wx.Frame):
6457
6826
  self.add_object('cloud', newobj=mycloud, ToCheck=True, id='Bridges')
6458
6827
 
6459
6828
  elif itemlabel == _('Create cloud points from buildings'):
6460
- autoscale=False
6829
+
6461
6830
  if self.mylazdata is None:
6462
6831
  self.init_laz_from_numpy()
6463
6832
 
@@ -6476,8 +6845,6 @@ class WolfMapViewer(wx.Frame):
6476
6845
 
6477
6846
  elif itemlabel == _('Create LAZ viewer'):
6478
6847
 
6479
- autoscale = False
6480
-
6481
6848
  laz_source = self._select_laz_source()
6482
6849
  if laz_source is None:
6483
6850
  return
@@ -6505,10 +6872,11 @@ class WolfMapViewer(wx.Frame):
6505
6872
  self.myviewer = myviewer(laz_source, ass_values[idx]) #, palette_classif = self.mylazdata_colors)
6506
6873
 
6507
6874
  elif itemlabel == _('Clip LAZ grid on current zoom'):
6875
+
6508
6876
  if self.mylazgrid is None:
6509
6877
  logging.warning(_('No gridded LAZ data loaded !'))
6510
6878
  return
6511
- autoscale=False
6879
+
6512
6880
  self.clip_laz_gridded()
6513
6881
 
6514
6882
  if self.mylazdata is None:
@@ -6530,9 +6898,10 @@ class WolfMapViewer(wx.Frame):
6530
6898
  dlg.Destroy()
6531
6899
 
6532
6900
  if decimate_fact > 0:
6533
- self.decimate_data(decimate_fact)
6901
+ self.decimate_laz_data(decimate_fact)
6534
6902
 
6535
6903
  elif itemlabel == _('Fill active array from LAZ data'):
6904
+
6536
6905
  if self.mylazgrid is None:
6537
6906
  logging.warning('')
6538
6907
  return
@@ -6540,10 +6909,10 @@ class WolfMapViewer(wx.Frame):
6540
6909
  logging.warning(_('No active array -- select an array first and retry!'))
6541
6910
  return
6542
6911
 
6543
- autoscale = False
6544
6912
  self.fill_active_array_from_laz(self.active_array)
6545
6913
 
6546
6914
  elif itemlabel == _('Count LAZ data in cells'):
6915
+
6547
6916
  if self.mylazgrid is None:
6548
6917
  logging.warning('')
6549
6918
  return
@@ -6551,7 +6920,6 @@ class WolfMapViewer(wx.Frame):
6551
6920
  logging.warning(_('No active array -- select an array first and retry!'))
6552
6921
  return
6553
6922
 
6554
- autoscale = False
6555
6923
  self.count_active_array_from_laz(self.active_array)
6556
6924
 
6557
6925
  elif itemlabel == _('Select cells in array from LAZ data'):
@@ -6562,15 +6930,13 @@ class WolfMapViewer(wx.Frame):
6562
6930
  logging.warning(_('No active array -- select an array first and retry!'))
6563
6931
  return
6564
6932
 
6565
- autoscale = False
6566
6933
  self.select_active_array_from_laz(self.active_array)
6567
6934
 
6568
6935
  elif itemlabel == _('Plot LAZ around active vector'):
6569
- autoscale = False
6570
6936
  self.plot_laz_around_active_vec()
6571
6937
 
6572
6938
  elif itemlabel == _('Plot LAZ around temporary vector'):
6573
- autoscale = False
6939
+
6574
6940
  self.active_vector = vector()
6575
6941
  self.active_vector.add_vertex(wolfvertex(0.,0.))
6576
6942
  self.mimicme()
@@ -6580,11 +6946,10 @@ class WolfMapViewer(wx.Frame):
6580
6946
  elif itemlabel == _('Change colors - Classification'):
6581
6947
 
6582
6948
  if self.mylazgrid is not None:
6583
- autoscale = False
6584
6949
  self.mylazgrid.colors.interactive_update_colors()
6585
6950
 
6586
6951
  elif itemlabel == _('Multiviewer'):
6587
- autoscale = False
6952
+
6588
6953
  dlg = wx.NumberEntryDialog(self, _("Additional viewers"), _("How many?"), _("How many additional viewers?"),1, 0, 5)
6589
6954
  ret = dlg.ShowModal()
6590
6955
 
@@ -6594,8 +6959,21 @@ class WolfMapViewer(wx.Frame):
6594
6959
 
6595
6960
  nb = dlg.GetValue()
6596
6961
  dlg.Destroy()
6597
- for i in range(nb):
6598
- self.add_viewer_and_link()
6962
+
6963
+ if nb > 0:
6964
+
6965
+ # Renaming the current viewer
6966
+ dlg = wx.TextEntryDialog(None, _('New name for the current viewer'), _('Rename'), self.viewer_name, style=wx.OK | wx.CANCEL)
6967
+ ret = dlg.ShowModal()
6968
+ if ret == wx.ID_OK:
6969
+ self.viewer_name = dlg.GetValue()
6970
+ self.SetName(self.viewer_name)
6971
+ dlg.Destroy()
6972
+
6973
+ for i in range(nb):
6974
+ self.add_viewer_and_link()
6975
+ else:
6976
+ logging.warning(_('No additional viewer !'))
6599
6977
 
6600
6978
  elif itemlabel == _('3D viewer'):
6601
6979
 
@@ -6615,8 +6993,6 @@ class WolfMapViewer(wx.Frame):
6615
6993
  self.active_viewer3d.add_array(curarray.idx, curarray._array3d)
6616
6994
  self.active_viewer3d.autoscale()
6617
6995
 
6618
- pass
6619
-
6620
6996
  elif itemlabel == _('Create/Open multiblock model'):
6621
6997
 
6622
6998
  self.create_2D_MB_model()
@@ -6635,6 +7011,8 @@ class WolfMapViewer(wx.Frame):
6635
7011
 
6636
7012
  elif itemlabel == _('Set comparison'):
6637
7013
 
7014
+ autoscale = True
7015
+
6638
7016
  # Comparaison de deux résultats ou de deux matrices
6639
7017
 
6640
7018
  self.compare_results = Compare_Arrays_Results(self, share_cmap_array= True, share_cmap_diff= True)
@@ -6651,6 +7029,7 @@ class WolfMapViewer(wx.Frame):
6651
7029
  self.compare_results.bake()
6652
7030
 
6653
7031
  elif id == wx.ID_EXIT:
7032
+
6654
7033
  dlg = wx.MessageDialog(None,_('Do you really want to quit?'), style = wx.YES_NO|wx.NO_DEFAULT)
6655
7034
  ret=dlg.ShowModal()
6656
7035
  if ret == wx.ID_YES:
@@ -6736,6 +7115,7 @@ class WolfMapViewer(wx.Frame):
6736
7115
  self.add_object(which='array_lidar_second', ToCheck=True)
6737
7116
 
6738
7117
  elif id == wx.ID_FILE5:
7118
+
6739
7119
  def addscandir(mydir):
6740
7120
  for entry in scandir(mydir):
6741
7121
  if entry.is_dir():
@@ -6758,7 +7138,7 @@ class WolfMapViewer(wx.Frame):
6758
7138
  ToCheck=True,
6759
7139
  id=join(mydir, entry.name))
6760
7140
 
6761
- elif entry.name.endswith('.bin'):
7141
+ elif entry.name.endswith(('.bin', '.tif', '.npy')):
6762
7142
  self.add_object(which='array',
6763
7143
  filename=join(mydir, entry.name),
6764
7144
  ToCheck=True,
@@ -6782,26 +7162,22 @@ class WolfMapViewer(wx.Frame):
6782
7162
  self.add_object('array', newobj=newarray)
6783
7163
 
6784
7164
  elif itemlabel == _('Create view...'):
6785
- autoscale = False
6786
7165
 
6787
7166
  # Création d'une nouvelle vue
6788
7167
  newview = WolfViews(mapviewer=self)
6789
7168
  self.add_object('views', newobj=newview)
6790
7169
 
6791
7170
  elif itemlabel==_('Create Wolf2D manager ...'):
6792
- autoscale = False
6793
7171
 
6794
7172
  from .mesh2d.config_manager import config_manager_2D
6795
7173
  newmanager = config_manager_2D(mapviewer=self)
6796
7174
 
6797
7175
  elif itemlabel==_('Create scenarios manager ...'):
6798
- autoscale = False
6799
7176
 
6800
7177
  from .scenario.config_manager import Config_Manager_2D_GPU
6801
7178
  newmanager = Config_Manager_2D_GPU(mapviewer=self, create_ui_if_wx=True)
6802
7179
 
6803
7180
  elif itemlabel == _('Create acceptability manager...'):
6804
- autoscale = False
6805
7181
 
6806
7182
  from .acceptability.acceptability_gui import AcceptabilityGui
6807
7183
  newmanager = AcceptabilityGui()
@@ -6809,7 +7185,6 @@ class WolfMapViewer(wx.Frame):
6809
7185
  newmanager.Show()
6810
7186
 
6811
7187
  elif itemlabel==_('Create BC manager Wolf2D...'):
6812
- autoscale = False
6813
7188
 
6814
7189
  if self.active_array is not None:
6815
7190
 
@@ -6842,27 +7217,26 @@ class WolfMapViewer(wx.Frame):
6842
7217
  self.active_bc = self.mybc[-1]
6843
7218
 
6844
7219
  elif itemlabel == _('Create Wolf1D...'):
6845
- autoscale = False
7220
+
6846
7221
  self.frame_create1Dfrom2D = GuiNotebook1D(mapviewer= self)
6847
7222
  logging.info(_(f'New window available - Wolf1D.'))
6848
7223
 
6849
7224
  elif id == wx.ID_FILE7:
6850
- autoscale = False
7225
+
6851
7226
  # Création de nouveaux vecteurs
6852
7227
  newzones = Zones(parent=self)
6853
7228
  self.add_object('vector', newobj=newzones)
7229
+
6854
7230
  elif id == wx.ID_FILE8:
6855
- autoscale = False
6856
7231
  # Création d'un nouveau nuage de point
6857
7232
  newcloud = cloud_vertices()
6858
7233
  self.add_object('cloud', newobj=newcloud)
7234
+
6859
7235
  elif id in self.tools.keys():
6860
7236
  # gestion des actions
6861
7237
  self.ManageActions(id)
6862
- autoscale = False
6863
7238
 
6864
7239
  elif id == wx.ID_SAVE:
6865
- autoscale = False
6866
7240
 
6867
7241
  for obj in self.iterator_over_objects(draw_type.ARRAYS):
6868
7242
  obj: WolfArray
@@ -6881,7 +7255,6 @@ class WolfMapViewer(wx.Frame):
6881
7255
  obj.saveas()
6882
7256
 
6883
7257
  elif itemlabel == 'Save to image...':
6884
- autoscale = False
6885
7258
 
6886
7259
  fn, ds = self.save_canvasogl(mpl=True)
6887
7260
 
@@ -6889,11 +7262,11 @@ class WolfMapViewer(wx.Frame):
6889
7262
  self.assembly_images(all_images, mode= self.assembly_mode)
6890
7263
 
6891
7264
  elif itemlabel == _('Copy image...'):
6892
- autoscale = False
7265
+
6893
7266
  self.copy_canvasogl()
6894
7267
 
6895
7268
  elif itemlabel == _('Export...'):
6896
- autoscale = False
7269
+
6897
7270
  curarray: WolfArray
6898
7271
  curvec: vector
6899
7272
 
@@ -6941,7 +7314,7 @@ class WolfMapViewer(wx.Frame):
6941
7314
  del wait
6942
7315
 
6943
7316
  elif itemlabel == _('Import...'):
6944
- autoscale = False
7317
+
6945
7318
  curarray: WolfArray
6946
7319
 
6947
7320
  msg = ''
@@ -6995,7 +7368,7 @@ class WolfMapViewer(wx.Frame):
6995
7368
  del wait
6996
7369
 
6997
7370
  elif itemlabel == _('Compare...'):
6998
- autoscale = False
7371
+
6999
7372
  msg = ''
7000
7373
  if self.active_array is None:
7001
7374
  msg += _('Active array is None\n')
@@ -7012,7 +7385,6 @@ class WolfMapViewer(wx.Frame):
7012
7385
  self.update_blender_sculpting()
7013
7386
 
7014
7387
  elif itemlabel == _('Update...'):
7015
- autoscale = False
7016
7388
 
7017
7389
  msg = ''
7018
7390
  if self.active_array is None:
@@ -7028,7 +7400,7 @@ class WolfMapViewer(wx.Frame):
7028
7400
  self.update_blender_sculpting()
7029
7401
 
7030
7402
  elif id == wx.ID_SAVEAS:
7031
- autoscale = False
7403
+
7032
7404
  for obj in self.iterator_over_objects(draw_type.ARRAYS):
7033
7405
  obj: WolfArray
7034
7406
 
@@ -7052,11 +7424,6 @@ class WolfMapViewer(wx.Frame):
7052
7424
  if ret == wx.ID_OK:
7053
7425
  obj.saveas(fdlg.GetPath())
7054
7426
 
7055
- # elif id == ID_RUN_SIMULATION:
7056
- # from ..debug.test_glsim.wolf_gpu import load_sim_to_gpu
7057
- # print("Simulation")
7058
- # load_sim_to_gpu()
7059
-
7060
7427
  if len(self.myarrays) + len(self.myvectors) + len(self.myclouds) + len(self.mytri) + len(self.myres2D) + len(self.mytiles) + len(self.myimagestiles) + len(self.mypartsystems) == 2 and autoscale:
7061
7428
  # Trouve les bornzs si un seul élément est présent, sinon on conserve l'état du zoom
7062
7429
  self.Autoscale()
@@ -7503,6 +7870,44 @@ class WolfMapViewer(wx.Frame):
7503
7870
 
7504
7871
  return ret
7505
7872
 
7873
+ def save_arrays_indep(self, fn:str, mpl:bool= True, ds:float= 0., add_title:bool= True) -> tuple[(str, float), str]:
7874
+ """ Save each array in a separate file
7875
+
7876
+ :param fn: filename without extension -- '.png' will be added
7877
+ :param mpl: save as matplotlib image
7878
+ :param ds: Ticks size for matplotlib image
7879
+ :return: list of tuple ((filename, ds), viewer_name)
7880
+ """
7881
+
7882
+ # Get all checked arrays
7883
+ checked_arrays = self.get_list_keys(drawing_type= draw_type.ARRAYS, checked_state= True)
7884
+ old_active = self.active_array
7885
+
7886
+ if len(checked_arrays) == 0:
7887
+ logging.warning(_('No arrays checked for export'))
7888
+ return
7889
+
7890
+ def uncheck_all():
7891
+ # uncheck arrays
7892
+ for curarray in checked_arrays:
7893
+ self.uncheck_id(curarray, unload= False, forceresetOGL= False)
7894
+
7895
+ fn = str(fn)
7896
+ ret = []
7897
+ for idx, curel in enumerate(checked_arrays):
7898
+ uncheck_all()
7899
+ self.check_id(curel)
7900
+ self.active_array = self.get_obj_from_id(curel, drawtype= draw_type.ARRAYS)
7901
+ ret.append((self.save_canvasogl(fn + '_' + str(idx) + '.png', mpl, ds, add_title= add_title, arrayid_as_title=True), curel))
7902
+
7903
+ self.active_array = old_active
7904
+ for curarray in checked_arrays:
7905
+ self.check_id(curarray)
7906
+
7907
+ self.Refresh()
7908
+
7909
+ return ret
7910
+
7506
7911
  def assembly_images(self, all_images, mode:Literal['horizontal', 'vertical', 'square']= 'square'):
7507
7912
  """ Assembly images
7508
7913
 
@@ -7518,6 +7923,9 @@ class WolfMapViewer(wx.Frame):
7518
7923
 
7519
7924
  images = [Image.open(fn) for (fn, ds), viewername in all_images]
7520
7925
 
7926
+ if len(images) in [1,2] and (mode == 'square' or mode == 2):
7927
+ mode = 'horizontal'
7928
+
7521
7929
  widths, heights = zip(*(i.size for i in images))
7522
7930
 
7523
7931
  if mode == 'horizontal' or mode==0:
@@ -8858,6 +9266,24 @@ class WolfMapViewer(wx.Frame):
8858
9266
  else:
8859
9267
  logging.warning(_('Rebin not yet implemented for this type of object'))
8860
9268
 
9269
+ elif text == _('Set NullValue'):
9270
+
9271
+ if isinstance(self.selected_object, WolfArray):
9272
+ dlg = wx.TextEntryDialog(self, _('Enter the new null value :'), _('Set NullValue'), str(self.selected_object.array.data[0,0]))
9273
+ if dlg.ShowModal() == wx.ID_OK:
9274
+ res = dlg.GetValue()
9275
+ dlg.Destroy()
9276
+
9277
+ try:
9278
+ res = float(res)
9279
+ self.selected_object.nullvalue = res
9280
+ self.selected_object.mask_data(res)
9281
+ self.selected_object.reset_plot()
9282
+ self.Refresh()
9283
+ except:
9284
+ logging.warning(_('Invalid value for null value'))
9285
+ return
9286
+
8861
9287
  elif _('Convert to mono-block') in text:
8862
9288
 
8863
9289
  if isinstance(self.selected_object, WolfArrayMB):
@@ -8892,6 +9318,30 @@ class WolfMapViewer(wx.Frame):
8892
9318
  else:
8893
9319
  logging.warning(_('Convert to multi-blocks not yet implemented for this type of object'))
8894
9320
 
9321
+ elif _('Extract current step as IC') in text:
9322
+
9323
+ if isinstance(self.selected_object, Wolfresults_2D):
9324
+
9325
+ if self.selected_object.current_result is None or self.selected_object.current_result < 0 :
9326
+ logging.warning(_('No current step defined'))
9327
+ return
9328
+
9329
+ import shutil
9330
+
9331
+ logging.info(_('Extracting current step as IC'))
9332
+
9333
+ dir = Path(self.selected_object.filename).parent
9334
+ files = ['h.npy', 'qx.npy', 'qy.npy']
9335
+ for curfile in files:
9336
+ if (dir / curfile).exists():
9337
+ # prepend the file with __
9338
+ logging.info(f'File {curfile} already exists -- renaming it')
9339
+ shutil.copyfile(dir / curfile, dir / ('__' + curfile))
9340
+
9341
+ logging.info(_('Extracting current step as IC'))
9342
+ self.selected_object.export_as(Path(self.selected_object.filename).parent, [views_2D.WATERDEPTH, views_2D.QX, views_2D.QY], 'numpy', False)
9343
+ logging.info(_('Done !'))
9344
+
8895
9345
  elif _('Export to Shape file') in text:
8896
9346
 
8897
9347
  if isinstance(self.selected_object, Zones | Bridge | Weir):
@@ -10588,6 +11038,8 @@ class WolfMapViewer(wx.Frame):
10588
11038
  # CTRL+L : chargement d'une matrice sur base du nom de fichier de la tile\n \
10589
11039
  # \n \
10590
11040
  # ALT+C : Copy image"
11041
+ # ALT+SHIFT+C : Copy images from multiviewers \
11042
+ # CTRL+ALT+SHIFT+C : Copy images from all arrays as independent image \
10591
11043
 
10592
11044
  groups = ['Results', 'Particle system', 'Drawing', 'Arrays', 'Cross sections', 'Zones', 'Action', 'Tree', 'Tiles', 'GLTF/GLB', 'App']
10593
11045
 
@@ -10619,7 +11071,8 @@ class WolfMapViewer(wx.Frame):
10619
11071
  'Arrows': _('Drawing : lateral movements'),
10620
11072
  'c or C': _('Drawing : copy canvas to Clipboard wo axes'),
10621
11073
  'ALT+C': _('Drawing : copy canvas to Clipboard as Matplotlib image'),
10622
- 'ALT+SHIFT+C': _('Drawing : copy canvas to Clipboard as Matplotlib image with axes - linked arrays'),
11074
+ 'ALT+SHIFT+C': _('Drawing : copy canvas to Clipboard as Matplotlib image with axes - multiviewers'),
11075
+ 'CTRL+ALT+SHIFT+C': _('Drawing : copy canvas to Clipboard as Matplotlib image with axes - all arrays one by one'),
10623
11076
 
10624
11077
  'CTRL+o': _('Results : increase transparency of the current result'),
10625
11078
  'CTRL+O': _('Results : decrease transparency of the current result'),
@@ -10940,12 +11393,20 @@ class WolfMapViewer(wx.Frame):
10940
11393
  # Copie du canvas dans le clipboard pour transfert vers autre application
10941
11394
  # Copie des canvas liés
10942
11395
 
11396
+ if not self.linked:
11397
+ logging.error(_('No linked canvas to copy -- calling ALT+C instead'))
11398
+ self.copy_canvasogl()
11399
+ return
11400
+
10943
11401
  from tempfile import TemporaryDirectory
10944
11402
 
10945
11403
  logging.info(_('Creating images'))
10946
11404
 
10947
11405
  with TemporaryDirectory() as tmpdirname:
10948
11406
  all_images = self.save_linked_canvas(Path(tmpdirname) / 'fig', mpl= True, ds= self.ticks_size, add_title= True)
11407
+ if len(all_images) == 0:
11408
+ logging.error(_('No image to combine -- aborting !'))
11409
+ return
10949
11410
  im_assembly = self.assembly_images(all_images, mode= self.assembly_mode)
10950
11411
 
10951
11412
  logging.info(_('Creating images - done'))
@@ -10998,7 +11459,44 @@ class WolfMapViewer(wx.Frame):
10998
11459
 
10999
11460
  logging.info(_('Values copied to clipboard'))
11000
11461
 
11001
- elif key == ord('C') and ctrldown and altdown:
11462
+ elif key == ord('C') and ctrldown and altdown and shiftdown:
11463
+ # CTRL+ALT+SHIFT+C
11464
+ # Copie du canvas dans le clipboard pour transfert vers autre application
11465
+ # Une matrice est associée à chaque canvas
11466
+
11467
+ from tempfile import TemporaryDirectory
11468
+
11469
+ logging.info(_('Creating images'))
11470
+
11471
+ with TemporaryDirectory() as tmpdirname:
11472
+ all_images = self.save_arrays_indep(Path(tmpdirname) / 'fig', mpl= True, ds= self.ticks_size, add_title= True)
11473
+ if len(all_images) == 0:
11474
+ logging.error(_('No image to combine -- aborting !'))
11475
+ return
11476
+ im_assembly = self.assembly_images(all_images, mode= self.assembly_mode)
11477
+
11478
+ logging.info(_('Creating images - done'))
11479
+
11480
+ # Copy image to clipboard
11481
+ if im_assembly is not None:
11482
+ if wx.TheClipboard.Open():
11483
+
11484
+ #création d'un objet bitmap wx
11485
+ wxbitmap = wx.Bitmap().FromBuffer(im_assembly.width, im_assembly.height, im_assembly.tobytes())
11486
+
11487
+ # objet wx exportable via le clipboard
11488
+ dataobj = wx.BitmapDataObject()
11489
+ dataobj.SetBitmap(wxbitmap)
11490
+
11491
+ wx.TheClipboard.SetData(dataobj)
11492
+ wx.TheClipboard.Close()
11493
+ logging.info(_('Image copied to clipboard'))
11494
+ else:
11495
+ logging.error(_('Cannot open the clipboard'))
11496
+ else:
11497
+ logging.error(_('No image to copy to clipboard'))
11498
+
11499
+ elif key == ord('C') and ctrldown and altdown and not shiftdown:
11002
11500
  if self.active_array is None:
11003
11501
  dlg = wx.MessageDialog(self,
11004
11502
  _('The active array is None - Please active an array from which to copy the selection !'),
@@ -11372,9 +11870,11 @@ class WolfMapViewer(wx.Frame):
11372
11870
  tracks.append(_('Convert to mono-block'))
11373
11871
  tracks.append(_('Convert to mono-block (result)'))
11374
11872
  tracks.append(_('Convert to multi-blocks (result)'))
11873
+ tracks.append(_('Extract current step as IC (result)'))
11375
11874
  tracks.append(_('Export to Shape file'))
11376
11875
  tracks.append(_('Export active zone to Shape file'))
11377
11876
  tracks.append(_('Rebin'))
11877
+ tracks.append(_('Set NullValue'))
11378
11878
 
11379
11879
  # Récupération des items du menu contextuel
11380
11880
  menuitems = self.popupmenu.GetMenuItems()
@@ -11401,6 +11901,7 @@ class WolfMapViewer(wx.Frame):
11401
11901
  self.popupmenu.Append(wx.ID_ANY, _('Boundary conditions'), _('Boundary conditions'))
11402
11902
  self.popupmenu.Append(wx.ID_ANY, _('Contours'))
11403
11903
  self.popupmenu.Append(wx.ID_ANY, _('Rebin'), _('Change the spatial resolution'))
11904
+ self.popupmenu.Append(wx.ID_ANY, _('Set NullValue'), _('Set NullValue'))
11404
11905
 
11405
11906
  # Add specific menu items for WolfArrayMB
11406
11907
  if isinstance(self.selected_object, WolfArrayMB):
@@ -11410,6 +11911,7 @@ class WolfMapViewer(wx.Frame):
11410
11911
  if isinstance(self.selected_object, Wolfresults_2D):
11411
11912
  self.popupmenu.Append(wx.ID_ANY, _('Convert to mono-block (result)'), _('Convert to mono-block'))
11412
11913
  self.popupmenu.Append(wx.ID_ANY, _('Convert to multi-blocks (result)'), _('Convert to multi-blocks'))
11914
+ self.popupmenu.Append(wx.ID_ANY, _('Extract current step as IC (result)'), _('Extract current step as IC'))
11413
11915
 
11414
11916
  if isinstance(self.selected_object, Zones | Bridge | Weir):
11415
11917
  self.popupmenu.Append(wx.ID_ANY, _('Export to Shape file'), _('Export to Shape file'))