wolfhece 2.0.4__py3-none-any.whl → 2.0.6__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/GraphNotebook.py +0 -1
- wolfhece/GraphProfile.py +5 -14
- wolfhece/Lidar2002.py +0 -1
- wolfhece/PyCrosssections.py +21 -26
- wolfhece/PyDraw.py +219 -58
- wolfhece/PyGui.py +6 -3
- wolfhece/PyPalette.py +2 -2
- wolfhece/PyParams.py +48 -48
- wolfhece/PyVertex.py +1 -1
- wolfhece/PyVertexvectors.py +40 -4
- wolfhece/Results2DGPU.py +7 -6
- wolfhece/apps/WolfPython.png +0 -0
- wolfhece/bernoulli/NetworkOpenGL.py +1 -1
- wolfhece/cli.py +7 -0
- wolfhece/flow_SPWMI.py +1 -1
- wolfhece/friction_law.py +6 -6
- wolfhece/gpuview.py +1 -1
- wolfhece/hydrology/PyWatershed.py +9 -10
- wolfhece/lagrangian/emitter.py +1 -1
- wolfhece/lagrangian/example_domain.py +1 -1
- wolfhece/lagrangian/velocity_field.py +4 -4
- wolfhece/libs/WolfDll.dll +0 -0
- wolfhece/libs/WolfDll_CD.dll +0 -0
- wolfhece/libs/WolfOGL.c +28187 -28187
- wolfhece/mar/Interface_MAR_WOLF_objet.py +1004 -0
- wolfhece/mar/commontools.py +1289 -59
- wolfhece/mesh2d/bc_manager.py +89 -13
- wolfhece/mesh2d/cst_2D_boundary_conditions.py +12 -0
- wolfhece/mesh2d/wolf2dprev.py +1 -2
- wolfhece/pydike.py +1 -1
- wolfhece/pyshields.py +43 -43
- wolfhece/pywalous.py +2 -2
- wolfhece/scenario/config_manager.py +3 -1
- wolfhece/ui/wolf_multiselection_collapsiblepane.py +10 -10
- wolfhece/wolf_array.py +1298 -418
- wolfhece/wolf_texture.py +1 -1
- wolfhece/wolfresults_2D.py +124 -19
- {wolfhece-2.0.4.dist-info → wolfhece-2.0.6.dist-info}/METADATA +5 -1
- {wolfhece-2.0.4.dist-info → wolfhece-2.0.6.dist-info}/RECORD +42 -39
- {wolfhece-2.0.4.dist-info → wolfhece-2.0.6.dist-info}/WHEEL +0 -0
- {wolfhece-2.0.4.dist-info → wolfhece-2.0.6.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.0.4.dist-info → wolfhece-2.0.6.dist-info}/top_level.txt +0 -0
wolfhece/wolf_array.py
CHANGED
@@ -17,7 +17,7 @@ try:
|
|
17
17
|
except:
|
18
18
|
msg=_('Error importing OpenGL library')
|
19
19
|
msg+=_(' Python version : ' + sys.version)
|
20
|
-
msg+=_(' Please check your version of opengl32.dll -- conflict may exist between different
|
20
|
+
msg+=_(' Please check your version of opengl32.dll -- conflict may exist between different files present on your desktop')
|
21
21
|
raise Exception(msg)
|
22
22
|
|
23
23
|
import math
|
@@ -34,6 +34,7 @@ from shapely.ops import linemerge, substring
|
|
34
34
|
from os.path import dirname,basename,join
|
35
35
|
import logging
|
36
36
|
from typing import Literal
|
37
|
+
from copy import deepcopy
|
37
38
|
|
38
39
|
from .PyTranslate import _
|
39
40
|
from .GraphNotebook import PlotPanel
|
@@ -75,7 +76,7 @@ WOLF_ARRAY_MNAP_INTEGER = 20
|
|
75
76
|
WOLF_ARRAY_MB = [WOLF_ARRAY_MB_SINGLE, WOLF_ARRAY_MB_INTEGER, WOLF_ARRAY_MNAP_INTEGER]
|
76
77
|
|
77
78
|
|
78
|
-
def getkeyblock(i, addone=True):
|
79
|
+
def getkeyblock(i, addone=True) -> str:
|
79
80
|
"""
|
80
81
|
Name/Key of a block in the dictionnary of a WolfArrayMB instance
|
81
82
|
|
@@ -86,12 +87,22 @@ def getkeyblock(i, addone=True):
|
|
86
87
|
else:
|
87
88
|
return 'block' + str(i)
|
88
89
|
|
90
|
+
def decodekeyblock(key, addone=True) -> int:
|
91
|
+
"""
|
92
|
+
Decode key of a block in the dictionnary of a WolfArrayMB instance
|
93
|
+
|
94
|
+
For Fortran compatibility, addone is True by default so first block is "block1" and not "block0"
|
95
|
+
"""
|
96
|
+
if addone:
|
97
|
+
return int(key[5:])
|
98
|
+
else:
|
99
|
+
return int(key[5:]) - 1
|
89
100
|
class header_wolf():
|
90
101
|
"""
|
91
102
|
Header of WolfArray
|
92
103
|
|
93
104
|
In case of a mutliblock, the header have informations about all the blocks in head_blocks dictionnary.
|
94
|
-
|
105
|
+
Block keys are generated by "getkeyblock" function
|
95
106
|
"""
|
96
107
|
|
97
108
|
# FIXME It'd be wise to put the multiblock case into another class.
|
@@ -101,13 +112,19 @@ class header_wolf():
|
|
101
112
|
head_blocks: dict[str,"header_wolf"]
|
102
113
|
|
103
114
|
def __init__(self) -> None:
|
104
|
-
|
105
|
-
|
106
|
-
|
115
|
+
"""
|
116
|
+
Origin (origx, origy, [origz]) is the point in local space from which every other coordinates are measured.
|
117
|
+
|
118
|
+
Translation (translx, transly, [translz]) is the translation of the origin in global space. If translation is null, the origin is the same in local and global space. :-)
|
107
119
|
|
108
|
-
|
109
|
-
|
110
|
-
|
120
|
+
Resolution (dx, dy, [dz]) is the spatial resolution of the array.
|
121
|
+
|
122
|
+
Nullvalue is the value of the null value in the array.
|
123
|
+
|
124
|
+
(nbx, nby, [nbz]) are the number of cells in the array along X and Y [and Z]. It is the shape of the array.
|
125
|
+
|
126
|
+
@property nbdims is the number of dimensions of the array (2 or 3)
|
127
|
+
"""
|
111
128
|
|
112
129
|
self.origx = 0.0
|
113
130
|
self.origy = 0.0
|
@@ -127,9 +144,10 @@ class header_wolf():
|
|
127
144
|
|
128
145
|
self.head_blocks = {}
|
129
146
|
|
130
|
-
self.
|
147
|
+
self.nullvalue = 0.
|
131
148
|
|
132
149
|
def __str__(self) -> str:
|
150
|
+
""" Return a string representation of the header """
|
133
151
|
ret = ''
|
134
152
|
ret += _('Shape : {} x {} \n').format(self.nbx, self.nby)
|
135
153
|
ret += _('Resolution : {} x {} \n').format(self.dx, self.dy)
|
@@ -137,18 +155,59 @@ class header_wolf():
|
|
137
155
|
ret += _(' - Origin : ({} ; {}) \n').format(self.origx, self.origy)
|
138
156
|
ret += _(' - End : ({} ; {}) \n').format(self.origx + self.nbx * self.dx, self.origy +self.nby * self.dy)
|
139
157
|
ret += _(' - Widht x Height : {} x {} \n').format(self.nbx * self.dx, self.nby * self.dy)
|
158
|
+
ret += _('Null value :{}\n'.format(self.nullvalue))
|
140
159
|
|
141
160
|
return ret
|
142
161
|
|
162
|
+
@property
|
163
|
+
def nbdims(self):
|
164
|
+
if self.nbz == 0:
|
165
|
+
if self.nbx > 0 and self.nby > 0:
|
166
|
+
return 2
|
167
|
+
else:
|
168
|
+
return 0
|
169
|
+
elif self.nbz > 0:
|
170
|
+
return 3
|
171
|
+
else:
|
172
|
+
raise Exception(_('The number of dimensions is not correct'))
|
173
|
+
|
174
|
+
@nbdims.setter
|
175
|
+
def nbdims(self, value):
|
176
|
+
logging.warning(_('nbdims was an attribute of header_wolf.\nIt is now a read-only property.\nPlease use nbx, nby and nbz instead to define the shape of the array'))
|
177
|
+
raise Exception(_('This property is read-only'))
|
178
|
+
|
179
|
+
@property
|
180
|
+
def shape(self):
|
181
|
+
if self.nbdims == 2:
|
182
|
+
return (self.nbx, self.nby)
|
183
|
+
elif self.nbdims == 3:
|
184
|
+
return (self.nbx, self.nby, self.nbz)
|
185
|
+
else:
|
186
|
+
return (0, 0)
|
187
|
+
|
188
|
+
@shape.setter
|
189
|
+
def shape(self, value:tuple[int]):
|
190
|
+
if len(value) == 3:
|
191
|
+
self.nbx = value[0]
|
192
|
+
self.nby = value[1]
|
193
|
+
self.nbz = value[2]
|
194
|
+
elif len(value) == 2:
|
195
|
+
self.nbx = value[0]
|
196
|
+
self.nby = value[1]
|
197
|
+
self.nbz = 0
|
198
|
+
else:
|
199
|
+
raise Exception(_('The number of dimensions is not correct'))
|
200
|
+
|
143
201
|
@property
|
144
202
|
def nb_blocks(self):
|
145
203
|
return len(self.head_blocks)
|
146
204
|
|
147
205
|
def __getitem__(self, key:Union[int,str]=None):
|
148
206
|
"""
|
149
|
-
|
207
|
+
Return block header
|
150
208
|
|
151
|
-
:param key:int = block's index (0-based)
|
209
|
+
:param key:int = block's index (0-based) or key (str)
|
210
|
+
:return : header_wolf instance if key is found, None otherwise
|
152
211
|
"""
|
153
212
|
if key is None:
|
154
213
|
return self
|
@@ -163,17 +222,54 @@ class header_wolf():
|
|
163
222
|
else:
|
164
223
|
return None
|
165
224
|
|
166
|
-
def
|
225
|
+
def __setitem__(self, key:Union[int,str], value:"header_wolf"):
|
226
|
+
"""
|
227
|
+
Set block header
|
228
|
+
|
229
|
+
:param value = tuple (key, header_wolf)
|
230
|
+
|
231
|
+
'key' can be an int (0-based) or a str
|
232
|
+
If str, please use getkeyblock function to generate the key
|
233
|
+
"""
|
234
|
+
|
235
|
+
if isinstance(key,int):
|
236
|
+
_key = getkeyblock(key)
|
237
|
+
else:
|
238
|
+
_key = key
|
239
|
+
|
240
|
+
self.head_blocks[_key] = deepcopy(value)
|
241
|
+
|
242
|
+
def set_origin(self, x:float, y:float, z:float):
|
243
|
+
"""
|
244
|
+
Set origin
|
245
|
+
|
246
|
+
:param x = origin along X
|
247
|
+
:param y = origin along Y
|
248
|
+
:param z = origin along Z
|
249
|
+
"""
|
167
250
|
self.origx = x
|
168
251
|
self.origy = y
|
169
252
|
self.origz = z
|
170
253
|
|
171
|
-
def
|
254
|
+
def set_translation(self, tr_x:float, tr_y:float, tr_z:float):
|
255
|
+
"""
|
256
|
+
Set translation
|
257
|
+
|
258
|
+
:param tr_x = translation along X
|
259
|
+
:param tr_y = translation along Y
|
260
|
+
:param tr_z = translation along Z
|
261
|
+
"""
|
172
262
|
self.translx = tr_x
|
173
263
|
self.transly = tr_y
|
174
264
|
self.translz = tr_z
|
175
265
|
|
176
266
|
def get_bounds(self, abs=True):
|
267
|
+
"""
|
268
|
+
Return bounds in coordinates
|
269
|
+
|
270
|
+
:param abs = if True, add translation to (x, y) (coordinate to global space)
|
271
|
+
:return : tuple of two lists of two floats - ([xmin, xmax],[ymin, ymax])
|
272
|
+
"""
|
177
273
|
if abs:
|
178
274
|
return ([self.origx + self.translx, self.origx + self.translx + float(self.nbx) * self.dx],
|
179
275
|
[self.origy + self.transly, self.origy + self.transly + float(self.nby) * self.dy])
|
@@ -181,13 +277,19 @@ class header_wolf():
|
|
181
277
|
return ([self.origx, self.origx + float(self.nbx) * self.dx],
|
182
278
|
[self.origy, self.origy + float(self.nby) * self.dy])
|
183
279
|
|
184
|
-
def get_bounds_ij(self, abs=
|
280
|
+
def get_bounds_ij(self, abs=False):
|
281
|
+
"""
|
282
|
+
Return bounds in indices
|
283
|
+
|
284
|
+
Firstly, get_bounds is called to get bounds in coordinates and then get_ij_from_xy is called to get bounds in indices.
|
185
285
|
|
286
|
+
:param abs = if True, add translation to (x, y) (coordinate to global space)
|
287
|
+
"""
|
186
288
|
mybounds = self.get_bounds(abs)
|
187
289
|
|
188
290
|
return (
|
189
|
-
[self.get_ij_from_xy(mybounds[0][0], mybounds[1][0]), self.get_ij_from_xy(mybounds[0][1], mybounds[0][0])],
|
190
|
-
[self.get_ij_from_xy(mybounds[0][0], mybounds[1][1]), self.get_ij_from_xy(mybounds[0][1], mybounds[1][1])])
|
291
|
+
[self.get_ij_from_xy(mybounds[0][0], mybounds[1][0], abs=abs), self.get_ij_from_xy(mybounds[0][1], mybounds[0][0], abs=abs)],
|
292
|
+
[self.get_ij_from_xy(mybounds[0][0], mybounds[1][1], abs=abs), self.get_ij_from_xy(mybounds[0][1], mybounds[1][1], abs=abs)])
|
191
293
|
|
192
294
|
def get_ij_from_xy(self, x:float, y:float, z:float=0., scale:float=1., aswolf:bool=False, abs:bool=True, forcedims2:bool=False) -> Union[tuple[np.int32,np.int32], tuple[np.int32,np.int32,np.int32]]:
|
193
295
|
"""
|
@@ -251,7 +353,7 @@ class header_wolf():
|
|
251
353
|
locxy[:,1] -= self.transly
|
252
354
|
|
253
355
|
i = np.int32(locxy[:,0] / (self.dx * scale))
|
254
|
-
j = np.int32(locxy[:,
|
356
|
+
j = np.int32(locxy[:,1] / (self.dy * scale))
|
255
357
|
|
256
358
|
if aswolf:
|
257
359
|
i += 1
|
@@ -261,7 +363,7 @@ class header_wolf():
|
|
261
363
|
locxy[:,2] -= self.origz
|
262
364
|
if abs:
|
263
365
|
locxy[:,2] -= self.translz
|
264
|
-
k = np.int32(locxy[:,
|
366
|
+
k = np.int32(locxy[:,2] / (self.dz * scale))
|
265
367
|
|
266
368
|
if aswolf:
|
267
369
|
k += 1
|
@@ -353,13 +455,47 @@ class header_wolf():
|
|
353
455
|
xy[:,0] = (np.float64( (ij[:,0])+decali) + .5) * (self.dx*scale) + self.origx + tr_x
|
354
456
|
xy[:,1] = (np.float64( (ij[:,1])+decalj) + .5) * (self.dy*scale) + self.origy + tr_y
|
355
457
|
|
356
|
-
if self.nbdims == 3 and ij.shape[
|
458
|
+
if self.nbdims == 3 and ij.shape[1]==3:
|
357
459
|
xy[:,2] = (np.float64( (ij[:,2])+decalk) + .5) * (self.dz*scale) + self.origz + tr_z
|
358
460
|
|
359
461
|
return xy
|
360
462
|
|
361
|
-
def
|
463
|
+
def ij2xy(self, i:int, j:int, k:int=0, scale:float=1., aswolf:bool=False, abs:bool=True) -> Union[tuple[np.float64,np.float64], tuple[np.float64,np.float64,np.float64]]:
|
464
|
+
""" alias for get_xy_from_ij """
|
465
|
+
return self.get_xy_from_ij(i, j, k, scale, aswolf, abs)
|
466
|
+
|
467
|
+
def ij2xy(self, ij:np.ndarray, scale:float=1., aswolf:bool=False, abs:bool=True) -> np.ndarray:
|
468
|
+
""" alias for get_xy_from_ij_array """
|
469
|
+
return self.get_xy_from_ij_array(ij, scale, aswolf, abs)
|
470
|
+
|
471
|
+
def xy2ij(self, x:float, y:float, z:float=0., scale:float=1., aswolf:bool=False, abs:bool=True, forcedims2:bool=False) -> Union[tuple[np.int32,np.int32], tuple[np.int32,np.int32,np.int32]]:
|
472
|
+
""" alias for get_ij_from_xy """
|
473
|
+
return self.get_ij_from_xy(x, y, z, scale, aswolf, abs, forcedims2)
|
362
474
|
|
475
|
+
def xy2ij(self, xy:np.ndarray, scale:float=1., aswolf:bool=False, abs:bool=True) -> np.ndarray:
|
476
|
+
""" alias for get_xy_from_ij_array """
|
477
|
+
return self.get_xy_from_ij_array(xy, scale, aswolf, abs)
|
478
|
+
|
479
|
+
def xyz2ijk(self, xyz:np.ndarray, scale:float=1., aswolf:bool=False, abs:bool=True) -> np.ndarray:
|
480
|
+
""" alias for get_xy_from_ij_array """
|
481
|
+
assert xyz.shape[1] == 3, _('xyz must be a 2D array with 3 columns')
|
482
|
+
return self.get_xy_from_ij_array(xyz, scale, aswolf, abs)
|
483
|
+
|
484
|
+
def ijk2xyz(self, ijk:np.ndarray, scale:float=1., aswolf:bool=False, abs:bool=True) -> np.ndarray:
|
485
|
+
""" alias for get_xy_from_ij_array """
|
486
|
+
assert ijk.shape[1] == 3, _('ijk must be a 2D array with 3 columns')
|
487
|
+
return self.get_xy_from_ij_array(ijk, scale, aswolf, abs)
|
488
|
+
|
489
|
+
|
490
|
+
def find_intersection(self, other:"header_wolf", ij:bool = False) -> Union[tuple[list[float],list[float]], tuple[list[list[float]],list[list[float]]]]:
|
491
|
+
"""
|
492
|
+
Find the intersection of two header
|
493
|
+
|
494
|
+
@arg other: other header
|
495
|
+
@arg ij: if True, return indices instead of coordinates
|
496
|
+
|
497
|
+
:return: None or tuple of two lists of two floats - ([xmin, xmax],[ymin, ymax]) or indices in each header (if ij=True) [[imin1, imax1], [jmin1, jmax1]], [[imin2, imax2], [jmin2, jmax2]]
|
498
|
+
"""
|
363
499
|
mybounds = self.get_bounds()
|
364
500
|
otherbounds = other.get_bounds()
|
365
501
|
|
@@ -387,7 +523,12 @@ class header_wolf():
|
|
387
523
|
else:
|
388
524
|
return ([ox, ex], [oy, ey])
|
389
525
|
|
390
|
-
def find_union(self, other):
|
526
|
+
def find_union(self, other:"header_wolf") -> tuple[list[float],list[float]]:
|
527
|
+
"""
|
528
|
+
Find the union of two header
|
529
|
+
|
530
|
+
:return: tuple of two lists of two floats - ([xmin, xmax],[ymin, ymax])
|
531
|
+
"""
|
391
532
|
|
392
533
|
mybounds = self.get_bounds()
|
393
534
|
otherbounds = other.get_bounds()
|
@@ -400,7 +541,16 @@ class header_wolf():
|
|
400
541
|
return ([ox, ex], [oy, ey])
|
401
542
|
|
402
543
|
def read_txt_header(self, filename:str):
|
403
|
-
"""
|
544
|
+
"""
|
545
|
+
Read informations from header .txt
|
546
|
+
|
547
|
+
:param filename : path and filename of the basefile
|
548
|
+
|
549
|
+
If filename is a Path object, it is converted to a string
|
550
|
+
If filename ends with '.tif', nothing is done because infos are in the .tif file
|
551
|
+
If filename ends with '.flt', a .hdr file must be present and it will be read
|
552
|
+
Otherwise, a filename.txt file must be present
|
553
|
+
"""
|
404
554
|
if isinstance(filename, Path):
|
405
555
|
filename = str(filename)
|
406
556
|
|
@@ -483,7 +633,6 @@ class header_wolf():
|
|
483
633
|
|
484
634
|
decal = 9
|
485
635
|
if self.wolftype == WOLF_ARRAY_FULL_SINGLE_3D:
|
486
|
-
self.nbdims = 3
|
487
636
|
tmp = lines[9].split(':')
|
488
637
|
self.nbz = int(tmp[1])
|
489
638
|
tmp = lines[10].split(':')
|
@@ -525,11 +674,13 @@ class header_wolf():
|
|
525
674
|
wolftype:int,
|
526
675
|
forceupdate:bool=False):
|
527
676
|
"""
|
528
|
-
|
677
|
+
Writing the header to a text file
|
529
678
|
|
530
|
-
|
531
|
-
wolftype : type de la matrice WOLF_ARRAY_*
|
679
|
+
Nullvalue is not written
|
532
680
|
|
681
|
+
:param filename : path and filename with '.txt' extension, which will NOT be automatically added
|
682
|
+
:param wolftype : type of the WOLF_ARRAY_* array
|
683
|
+
:param forceupdate : if True, the file is rewritten even if it already exists
|
533
684
|
"""
|
534
685
|
|
535
686
|
assert wolftype in [WOLF_ARRAY_CSR_DOUBLE, WOLF_ARRAY_FULL_SINGLE, WOLF_ARRAY_FULL_DOUBLE, WOLF_ARRAY_SYM_DOUBLE, WOLF_ARRAY_FULL_LOGICAL, WOLF_ARRAY_CSR_DOUBLE, WOLF_ARRAY_FULL_INTEGER, WOLF_ARRAY_FULL_SINGLE_3D, WOLF_ARRAY_FULL_INTEGER8, WOLF_ARRAY_MB_SINGLE, WOLF_ARRAY_MB_INTEGER, WOLF_ARRAY_FULL_INTEGER16, WOLF_ARRAY_MNAP_INTEGER]
|
@@ -564,8 +715,15 @@ class header_wolf():
|
|
564
715
|
f.write('DX :\t{0}\n'.format(str(curhead.dx)))
|
565
716
|
f.write('DY :\t{0}\n'.format(str(curhead.dy)))
|
566
717
|
|
567
|
-
def is_like(self,other):
|
568
|
-
"""
|
718
|
+
def is_like(self, other:"header_wolf", check_mb:bool=False) -> bool:
|
719
|
+
"""
|
720
|
+
Comparison of two headers
|
721
|
+
|
722
|
+
:param other : other header to compare
|
723
|
+
:param check_mb : if True, the comparison is done on the blocks too
|
724
|
+
|
725
|
+
The nullvalue is not taken into account
|
726
|
+
"""
|
569
727
|
test = True
|
570
728
|
test &= self.origx == other.origx
|
571
729
|
test &= self.origy == other.origy
|
@@ -585,8 +743,151 @@ class header_wolf():
|
|
585
743
|
|
586
744
|
test &= self.nbdims == other.nbdims
|
587
745
|
|
746
|
+
if check_mb:
|
747
|
+
test &= self.nb_blocks == other.nb_blocks
|
748
|
+
for block1, block2 in zip(self.head_blocks.values(), other.head_blocks.values()):
|
749
|
+
test &= block1.is_like(block2)
|
750
|
+
|
588
751
|
return test
|
589
752
|
|
753
|
+
def align2grid(self, x1:float, y1:float, eps:float=0.0001) -> tuple[float,float]:
|
754
|
+
""" Align coordinates to nearest grid point """
|
755
|
+
|
756
|
+
if x1-self.origx < 0:
|
757
|
+
x2 = np.round((x1 - self.origx + eps) / self.dx) * self.dx + self.origx
|
758
|
+
else:
|
759
|
+
x2 = np.round((x1 - self.origx - eps) / self.dx) * self.dx + self.origx
|
760
|
+
|
761
|
+
if y1-self.origy < 0:
|
762
|
+
y2 = np.round((y1 - self.origy + eps) / self.dy) * self.dy + self.origy
|
763
|
+
else:
|
764
|
+
y2 = np.round((y1 - self.origy - eps) / self.dy) * self.dy + self.origy
|
765
|
+
|
766
|
+
return x2, y2
|
767
|
+
|
768
|
+
def _rasterize_segment(self,
|
769
|
+
x1:float, y1:float,
|
770
|
+
x2:float, y2:float,
|
771
|
+
xstart:float=None, ystart:float=None) -> list[list[float]]:
|
772
|
+
"""
|
773
|
+
Rasterize a segment according to the grid
|
774
|
+
|
775
|
+
:param x1: x coordinate of the first point
|
776
|
+
:param y1: y coordinate of the first point
|
777
|
+
:param x2: x coordinate of the second point
|
778
|
+
:param y2: y coordinate of the second point
|
779
|
+
:param xstart: x coordinate of the starting point
|
780
|
+
:param ystart: y coordinate of the starting point
|
781
|
+
|
782
|
+
:return: numpy array of the rasterized segment
|
783
|
+
"""
|
784
|
+
|
785
|
+
if xstart is None and ystart is None:
|
786
|
+
xstart, ystart = self.align2grid(x1, y1)
|
787
|
+
|
788
|
+
x2, y2 = self.align2grid(x2, y2)
|
789
|
+
|
790
|
+
points=[]
|
791
|
+
points.append([xstart, ystart])
|
792
|
+
|
793
|
+
length = 99999.
|
794
|
+
prec = min(self.dx, self.dy)
|
795
|
+
direction = np.array([x2-xstart, y2-ystart])
|
796
|
+
length = np.linalg.norm(direction)
|
797
|
+
direction /= length
|
798
|
+
|
799
|
+
while length >= prec:
|
800
|
+
|
801
|
+
if np.abs(direction[0])>= np.abs(direction[1]):
|
802
|
+
xstart += self.dx * np.sign(direction[0])
|
803
|
+
else:
|
804
|
+
ystart += self.dy * np.sign(direction[1])
|
805
|
+
|
806
|
+
points.append([xstart, ystart])
|
807
|
+
|
808
|
+
direction = np.array([x2-xstart, y2-ystart])
|
809
|
+
length = np.linalg.norm(direction)
|
810
|
+
direction /= length
|
811
|
+
|
812
|
+
return points
|
813
|
+
|
814
|
+
def rasterize_vector(self, vector2raster:vector, outformat:Union[np.ndarray, vector]=vector) -> Union[np.ndarray,vector]:
|
815
|
+
"""
|
816
|
+
Rasterize a vector according to the grid
|
817
|
+
|
818
|
+
:param vector2raster: vector to rasterize
|
819
|
+
:param outformat: output format (np.ndarray or vector)
|
820
|
+
"""
|
821
|
+
|
822
|
+
assert outformat in [np.ndarray, vector], _('outformat must be np.ndarray or vector')
|
823
|
+
|
824
|
+
# get the vertices of the vector
|
825
|
+
xy = vector2raster.asnparray().tolist()
|
826
|
+
|
827
|
+
# rasterize the vector
|
828
|
+
rasterized = []
|
829
|
+
rasterized += self._rasterize_segment(xy[0][0], xy[0][1], xy[1][0], xy[1][1])
|
830
|
+
|
831
|
+
for i in range(1, len(xy)-1):
|
832
|
+
out = self._rasterize_segment(xy[i][0], xy[i][1],
|
833
|
+
xy[i+1][0], xy[i+1][1],
|
834
|
+
rasterized[-1][0], rasterized[-1][1])
|
835
|
+
rasterized += out[1:]
|
836
|
+
|
837
|
+
# get the indices of the rasterized vector
|
838
|
+
xy = np.array(rasterized)
|
839
|
+
|
840
|
+
if outformat is np.ndarray:
|
841
|
+
return xy
|
842
|
+
elif outformat is vector:
|
843
|
+
#create new vector
|
844
|
+
newvector = vector()
|
845
|
+
newvector.add_vertices_from_array(xy)
|
846
|
+
|
847
|
+
return newvector
|
848
|
+
|
849
|
+
def get_xy_infootprint_vect(self, myvect: vector) -> np.ndarray:
|
850
|
+
"""
|
851
|
+
Return the coordinates of the cells in the footprint of a vector
|
852
|
+
|
853
|
+
:param myvect = target vector
|
854
|
+
"""
|
855
|
+
|
856
|
+
myptsij = self.get_ij_infootprint_vect(myvect)
|
857
|
+
mypts=np.asarray(myptsij.copy(),dtype=np.float64)
|
858
|
+
mypts[:,0] = (mypts[:,0]+.5)*self.dx +self.origx +self.translx
|
859
|
+
mypts[:,1] = (mypts[:,1]+.5)*self.dy +self.origy +self.transly
|
860
|
+
|
861
|
+
return mypts,myptsij
|
862
|
+
|
863
|
+
def get_ij_infootprint_vect(self, myvect: vector) -> np.ndarray:
|
864
|
+
"""
|
865
|
+
Return the indices of the cells in the footprint of a vector
|
866
|
+
|
867
|
+
:param myvect = target vector
|
868
|
+
"""
|
869
|
+
|
870
|
+
i1, j1 = self.get_ij_from_xy(myvect.xmin, myvect.ymin)
|
871
|
+
i2, j2 = self.get_ij_from_xy(myvect.xmax, myvect.ymax)
|
872
|
+
i1 = max(i1,0) # FIXME Why ??? How could i,j be negative ? --> because this fucntion can be called with a vector that is not in the array (e.g. a vector defined by clicks in the UI)
|
873
|
+
j1 = max(j1,0)
|
874
|
+
i2 = min(i2,self.nbx-1)
|
875
|
+
j2 = min(j2,self.nby-1)
|
876
|
+
xv,yv = np.meshgrid(np.arange(i1,i2+1),np.arange(j1,j2+1))
|
877
|
+
mypts = np.hstack((xv.flatten()[:,np.newaxis],yv.flatten()[:,np.newaxis]))
|
878
|
+
|
879
|
+
return mypts
|
880
|
+
|
881
|
+
def convert_xy2ij_np(self,xy):
|
882
|
+
""" Convert XY coordinates to IJ indices with Numpy without any check/options """
|
883
|
+
return np.asarray((xy[:,0]-self.origx -self.translx)/self.dx-.5,dtype=np.int32), \
|
884
|
+
np.asarray((xy[:,1]-self.origy -self.transly)/self.dy-.5,dtype=np.int32)
|
885
|
+
|
886
|
+
def convert_ij2xy_np(self,xy):
|
887
|
+
""" Convert IJ indices to XY coordinates with Numpy without any check/options """
|
888
|
+
return np.asarray((xy[:,0]+.5)*self.dx+self.origx +self.translx ,dtype=np.float64), \
|
889
|
+
np.asarray((xy[:,1]+.5)*self.dy+self.origy +self.transly ,dtype=np.float64)
|
890
|
+
|
590
891
|
class NewArray(wx.Dialog):
|
591
892
|
"""
|
592
893
|
wx GUI interaction to create a new WolfArray
|
@@ -665,9 +966,10 @@ class NewArray(wx.Dialog):
|
|
665
966
|
self.Centre(wx.BOTH)
|
666
967
|
|
667
968
|
|
969
|
+
#FIXME : Generalize to 3D
|
668
970
|
class CropDialog(wx.Dialog):
|
669
971
|
"""
|
670
|
-
wx GUI interaction to crop array's data
|
972
|
+
wx GUI interaction to crop 2D array's data
|
671
973
|
|
672
974
|
Used in "read_data" of a WolfArray
|
673
975
|
"""
|
@@ -747,6 +1049,8 @@ class CropDialog(wx.Dialog):
|
|
747
1049
|
self.Centre(wx.BOTH)
|
748
1050
|
|
749
1051
|
def get_header(self):
|
1052
|
+
""" Return a header_wolf object with the values of the dialog """
|
1053
|
+
|
750
1054
|
myhead = header_wolf()
|
751
1055
|
myhead.origx = float(self.ox.Value)
|
752
1056
|
myhead.origy = float(self.oy.Value)
|
@@ -754,19 +1058,23 @@ class CropDialog(wx.Dialog):
|
|
754
1058
|
myhead.dy = float(self.dy.Value)
|
755
1059
|
myhead.nbx = int((float(self.ex.Value) - myhead.origx) / myhead.dx)
|
756
1060
|
myhead.nby = int((float(self.ey.Value) - myhead.origy) / myhead.dy)
|
757
|
-
myhead.nbdims = 2
|
758
1061
|
|
759
1062
|
return myhead
|
760
1063
|
|
761
1064
|
|
762
1065
|
class Ops_Array(wx.Frame):
|
763
1066
|
"""
|
764
|
-
|
1067
|
+
Operations wx.Frame on WolfArray class
|
765
1068
|
|
766
|
-
|
1069
|
+
This class is used to perform operations on a WolfArray
|
767
1070
|
"""
|
768
1071
|
|
769
1072
|
def __init__(self, parentarray:"WolfArray", mapviewer=None):
|
1073
|
+
""" Init the Ops_Array class
|
1074
|
+
|
1075
|
+
:param parentarray: WolfArray to operate on
|
1076
|
+
:param mapviewer: WolfMapViewer to update if necessary
|
1077
|
+
"""
|
770
1078
|
|
771
1079
|
self.parentarray:WolfArray
|
772
1080
|
self.parentarray = parentarray
|
@@ -777,6 +1085,7 @@ class Ops_Array(wx.Frame):
|
|
777
1085
|
|
778
1086
|
self.wx_exists = wx.App.Get() is not None
|
779
1087
|
|
1088
|
+
# active objects
|
780
1089
|
self.active_vector:vector = None
|
781
1090
|
self.active_zone:zone = None
|
782
1091
|
self.active_array:WolfArray = self.parentarray
|
@@ -793,7 +1102,7 @@ class Ops_Array(wx.Frame):
|
|
793
1102
|
self.set_GUI()
|
794
1103
|
|
795
1104
|
def get_mapviewer(self):
|
796
|
-
""" Retourne
|
1105
|
+
""" Retourne l'instance WolfMapViewer """
|
797
1106
|
return self.mapviewer
|
798
1107
|
|
799
1108
|
def get_linked_arrays(self):
|
@@ -980,20 +1289,28 @@ class Ops_Array(wx.Frame):
|
|
980
1289
|
|
981
1290
|
# Tools
|
982
1291
|
Toolssizer = wx.BoxSizer(wx.VERTICAL)
|
1292
|
+
|
983
1293
|
hbox = wx.BoxSizer(wx.HORIZONTAL)
|
1294
|
+
|
984
1295
|
self.lbl_nullval = wx.StaticText(self.tools,label=_('Null value'))
|
985
1296
|
self.txt_nullval = wx.TextCtrl(self.tools,value=str(self.parentarray.nullvalue), style=wx.TE_CENTER)
|
986
1297
|
self.txt_nullval.SetToolTip(_('Array null value'))
|
987
1298
|
hbox.Add(self.lbl_nullval, 0, wx.EXPAND|wx.ALL)
|
988
1299
|
hbox.Add(self.txt_nullval, 1, wx.EXPAND|wx.ALL)
|
989
1300
|
|
990
|
-
self.ApplyTools = wx.Button(self.tools, wx.ID_ANY, _("Apply
|
1301
|
+
self.ApplyTools = wx.Button(self.tools, wx.ID_ANY, _("Apply null value"), wx.DefaultPosition,
|
991
1302
|
wx.DefaultSize, 0)
|
992
1303
|
|
1304
|
+
|
1305
|
+
self.nullborder = wx.Button(self.tools, wx.ID_ANY, _("Null border"), wx.DefaultPosition,
|
1306
|
+
wx.DefaultSize, 0)
|
1307
|
+
|
993
1308
|
Toolssizer.Add(hbox, 0, wx.EXPAND)
|
994
1309
|
Toolssizer.Add(self.ApplyTools, 1, wx.EXPAND)
|
1310
|
+
Toolssizer.Add(self.nullborder, 1, wx.EXPAND)
|
995
1311
|
|
996
1312
|
self.ApplyTools.SetToolTip(_("Save modifications into memmory/object"))
|
1313
|
+
self.nullborder.SetToolTip(_("Set null value on the border of the array"))
|
997
1314
|
|
998
1315
|
self.tools.SetSizer(Toolssizer)
|
999
1316
|
self.tools.Layout()
|
@@ -1008,12 +1325,12 @@ class Ops_Array(wx.Frame):
|
|
1008
1325
|
bSizer16 = wx.BoxSizer(wx.VERTICAL)
|
1009
1326
|
|
1010
1327
|
selectmethodChoices = [_("by clicks"), _("inside active vector"), _("inside active zone"),
|
1011
|
-
_("inside temporary vector"), _("
|
1012
|
-
_("
|
1328
|
+
_("inside temporary vector"), _("along active vector"), _("along active zone"),
|
1329
|
+
_("along temporary vector")]
|
1013
1330
|
self.selectmethod = wx.RadioBox(self.selection, wx.ID_ANY, _("How to select nodes?"), wx.DefaultPosition,
|
1014
1331
|
wx.DefaultSize, selectmethodChoices, 1, wx.RA_SPECIFY_COLS)
|
1015
1332
|
self.selectmethod.SetSelection(0)
|
1016
|
-
self.selectmethod.SetToolTip(_("Selection mode : \n - one by one (keyboard shortcut N) \n- inside the currently activated polygon (keyboard shortcut V) \n- inside the currently activated zone (multipolygons) \n- inside a temporary polygon (keyboard shortcut B) \n-
|
1333
|
+
self.selectmethod.SetToolTip(_("Selection mode : \n - one by one (keyboard shortcut N) \n- inside the currently activated polygon (keyboard shortcut V) \n- inside the currently activated zone (multipolygons) \n- inside a temporary polygon (keyboard shortcut B) \n- along the currently activated polyline \n- along the currently activated zone (multipolylines) \n- along a temporary polyline"))
|
1017
1334
|
|
1018
1335
|
bSizer16.Add(self.selectmethod, 0, wx.ALL, 5)
|
1019
1336
|
|
@@ -1227,7 +1544,8 @@ class Ops_Array(wx.Frame):
|
|
1227
1544
|
self.saveas.Bind(wx.EVT_BUTTON, self.OnSaveasvec)
|
1228
1545
|
self.save.Bind(wx.EVT_BUTTON, self.OnSavevec)
|
1229
1546
|
self.ApplyOp.Bind(wx.EVT_BUTTON, self.OnApplyOpMath)
|
1230
|
-
self.ApplyTools.Bind(wx.EVT_BUTTON, self.
|
1547
|
+
self.ApplyTools.Bind(wx.EVT_BUTTON, self.OnApplyNullvalue)
|
1548
|
+
self.nullborder.Bind(wx.EVT_BUTTON, self.OnNullBorder)
|
1231
1549
|
self.SelectOp.Bind(wx.EVT_BUTTON, self.OnApplyOpSelect)
|
1232
1550
|
self.palapply.Bind(wx.EVT_BUTTON, self.Onupdatepal)
|
1233
1551
|
self.palsave.Bind(wx.EVT_BUTTON, self.Onsavepal)
|
@@ -1240,21 +1558,18 @@ class Ops_Array(wx.Frame):
|
|
1240
1558
|
self.histoupdateerase.Bind(wx.EVT_BUTTON, self.OnClickHistoUpdate)
|
1241
1559
|
|
1242
1560
|
def interpolation2D(self, event: wx.MouseEvent):
|
1561
|
+
""" calling Interpolation 2D """
|
1243
1562
|
self.parentarray.interpolation2D()
|
1244
1563
|
|
1245
1564
|
def Unmaskall(self, event: wx.MouseEvent):
|
1246
1565
|
"""
|
1247
|
-
|
1566
|
+
Unmask all values in the current array
|
1248
1567
|
@author Pierre Archambeau
|
1249
1568
|
"""
|
1250
|
-
|
1251
|
-
|
1252
|
-
curarray.mask_reset()
|
1253
|
-
curarray = self.parentarray
|
1254
|
-
curarray.updatepalette()
|
1255
|
-
curarray.delete_lists()
|
1569
|
+
self.parentarray.mask_reset()
|
1570
|
+
self.refresh_array()
|
1256
1571
|
|
1257
|
-
def Unmasksel(self,event:wx.MouseEvent):
|
1572
|
+
def Unmasksel(self, event:wx.MouseEvent):
|
1258
1573
|
"""
|
1259
1574
|
Enlève le masque des éléments sélectionnés
|
1260
1575
|
@author Pierre Archambeau
|
@@ -1271,17 +1586,12 @@ class Ops_Array(wx.Frame):
|
|
1271
1586
|
|
1272
1587
|
curarray.array.mask[destij[:, 0], destij[:, 1]] = False
|
1273
1588
|
|
1274
|
-
|
1275
|
-
curarray.delete_lists()
|
1589
|
+
self.refresh_array()
|
1276
1590
|
|
1277
1591
|
def InvertMask(self, event: wx.MouseEvent):
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
curarray.mask_invert()
|
1282
|
-
curarray = self.parentarray
|
1283
|
-
curarray.updatepalette()
|
1284
|
-
curarray.delete_lists()
|
1592
|
+
""" Invert mask """
|
1593
|
+
self.parentarray.mask_invert()
|
1594
|
+
self.refresh_array()
|
1285
1595
|
|
1286
1596
|
def interp2Dpolygons(self, event: wx.MouseEvent):
|
1287
1597
|
"""
|
@@ -1299,15 +1609,12 @@ class Ops_Array(wx.Frame):
|
|
1299
1609
|
dlg.Destroy()
|
1300
1610
|
|
1301
1611
|
actzone = self.active_zone
|
1302
|
-
curarray: WolfArray
|
1303
|
-
curarray = self.parentarray
|
1304
1612
|
|
1305
1613
|
for curvec in actzone.myvectors:
|
1306
1614
|
curvec: vector
|
1307
1615
|
self._interp2Dpolygon(curvec, method)
|
1308
1616
|
|
1309
|
-
|
1310
|
-
curarray.delete_lists()
|
1617
|
+
self.refresh_array()
|
1311
1618
|
|
1312
1619
|
def interp2Dpolygon(self, event: wx.MouseEvent):
|
1313
1620
|
"""
|
@@ -1324,14 +1631,9 @@ class Ops_Array(wx.Frame):
|
|
1324
1631
|
method = dlg.GetStringSelection()
|
1325
1632
|
dlg.Destroy()
|
1326
1633
|
|
1327
|
-
actzone = self.active_zone
|
1328
|
-
curarray: WolfArray
|
1329
|
-
curarray = self.parentarray
|
1330
|
-
|
1331
1634
|
self._interp2Dpolygon(self.active_vector, method)
|
1332
1635
|
|
1333
|
-
|
1334
|
-
curarray.delete_lists()
|
1636
|
+
self.refresh_array()
|
1335
1637
|
|
1336
1638
|
def _interp2Dpolygon(self, vect: vector, method):
|
1337
1639
|
"""
|
@@ -1370,28 +1672,21 @@ class Ops_Array(wx.Frame):
|
|
1370
1672
|
cf _interp2Dpolyline
|
1371
1673
|
"""
|
1372
1674
|
actzone = self.active_zone
|
1373
|
-
curarray: WolfArray
|
1374
|
-
curarray = self.parentarray
|
1375
1675
|
|
1376
1676
|
for curvec in actzone.myvectors:
|
1377
1677
|
curvec: vector
|
1378
1678
|
self._interp2Dpolyline(curvec)
|
1379
1679
|
|
1380
|
-
|
1381
|
-
curarray.delete_lists()
|
1680
|
+
self.refresh_array()
|
1382
1681
|
|
1383
1682
|
def interp2Dpolyline(self, event: wx.MouseEvent):
|
1384
1683
|
"""
|
1385
1684
|
Bouton d'interpolation sous la polyligne active
|
1386
1685
|
cf _interp2Dpolyline
|
1387
1686
|
"""
|
1388
|
-
curarray: WolfArray
|
1389
|
-
curarray = self.parentarray
|
1390
|
-
|
1391
1687
|
self._interp2Dpolyline(self.active_vector)
|
1392
1688
|
|
1393
|
-
|
1394
|
-
curarray.delete_lists()
|
1689
|
+
self.refresh_array()
|
1395
1690
|
|
1396
1691
|
def _interp2Dpolyline(self, vect: vector, usemask=True):
|
1397
1692
|
"""
|
@@ -1515,14 +1810,17 @@ class Ops_Array(wx.Frame):
|
|
1515
1810
|
self.reset_all_selection()
|
1516
1811
|
|
1517
1812
|
def OnApplyOpSelect(self, event):
|
1518
|
-
|
1813
|
+
""" Select nodes based on condition """
|
1519
1814
|
|
1815
|
+
# condition operator
|
1816
|
+
curcond = self.condition.GetSelection()
|
1817
|
+
# condition value
|
1520
1818
|
curcondvalue = float(self.condvalue.GetValue())
|
1521
1819
|
|
1522
1820
|
self.parentarray.mngselection.condition_select(curcond, curcondvalue)
|
1523
1821
|
|
1524
|
-
def
|
1525
|
-
|
1822
|
+
def OnApplyNullvalue(self, event:wx.MouseEvent):
|
1823
|
+
""" Apply null value to the array """
|
1526
1824
|
newnull = self.txt_nullval.Value
|
1527
1825
|
if newnull.lower() == 'nan':
|
1528
1826
|
newnull = np.nan
|
@@ -1532,25 +1830,52 @@ class Ops_Array(wx.Frame):
|
|
1532
1830
|
if self.parentarray.nullvalue!= newnull:
|
1533
1831
|
self.parentarray.nullvalue = newnull
|
1534
1832
|
self.parentarray.mask_data(newnull)
|
1535
|
-
self.
|
1536
|
-
if self.mapviewer is not None:
|
1537
|
-
self.mapviewer.Refresh()
|
1833
|
+
self.refresh_array()
|
1538
1834
|
|
1539
|
-
def
|
1835
|
+
def refresh_array(self):
|
1836
|
+
""" Force refresh of the parent array """
|
1837
|
+
self.parentarray.reset_plot()
|
1838
|
+
|
1839
|
+
def OnNullBorder(self, event:wx.MouseEvent):
|
1840
|
+
""" Nullify the border of the array """
|
1841
|
+
|
1842
|
+
dlg = wx.SingleChoiceDialog(None, "Choose the border width [number of nodes]", "Border width", [str(i) for i in range(1, 20)])
|
1843
|
+
|
1844
|
+
ret = dlg.ShowModal()
|
1845
|
+
if ret == wx.ID_CANCEL:
|
1846
|
+
dlg.Destroy()
|
1847
|
+
return
|
1540
1848
|
|
1849
|
+
borderwidth = int(dlg.GetStringSelection())
|
1850
|
+
|
1851
|
+
self.parentarray.nullify_border(borderwidth)
|
1852
|
+
|
1853
|
+
def OnApplyOpMath(self, event:wx.MouseEvent):
|
1854
|
+
""" Apply math operator to the array """
|
1855
|
+
|
1856
|
+
# operator type
|
1541
1857
|
curop = self.choiceop.GetSelection()
|
1858
|
+
# condition type
|
1542
1859
|
curcond = self.condition.GetSelection()
|
1543
1860
|
|
1861
|
+
# operator value
|
1544
1862
|
opval = self.opvalue.GetValue()
|
1545
1863
|
if opval.lower() == 'null' or opval.lower() == 'nan':
|
1546
1864
|
curopvalue = self.parentarray.nullvalue
|
1547
1865
|
else:
|
1548
1866
|
curopvalue = float(opval)
|
1549
|
-
|
1867
|
+
|
1868
|
+
# condition value
|
1869
|
+
curcondvalue = self.condvalue.GetValue()
|
1870
|
+
if curcondvalue.lower() == 'null' or curcondvalue.lower() == 'nan':
|
1871
|
+
curcondvalue = self.parentarray.nullvalue
|
1872
|
+
else:
|
1873
|
+
curcondvalue = float(curcondvalue)
|
1550
1874
|
|
1551
1875
|
self.parentarray.mngselection.treat_select(curop, curcond, curopvalue, curcondvalue)
|
1552
1876
|
|
1553
|
-
def Onmask(self, event):
|
1877
|
+
def Onmask(self, event:wx.MouseEvent):
|
1878
|
+
""" Mask nodes based on condition """
|
1554
1879
|
|
1555
1880
|
curop = self.choiceop.GetSelection()
|
1556
1881
|
curcond = self.condition.GetSelection()
|
@@ -1559,10 +1884,11 @@ class Ops_Array(wx.Frame):
|
|
1559
1884
|
curcondvalue = float(self.condvalue.GetValue())
|
1560
1885
|
|
1561
1886
|
self.parentarray.mngselection.mask_condition(curop, curcond, curopvalue, curcondvalue)
|
1562
|
-
self.
|
1563
|
-
|
1887
|
+
self.refresh_array()
|
1888
|
+
|
1889
|
+
def OnManageVectors(self, event:wx.MouseEvent):
|
1890
|
+
""" Open vector manager """
|
1564
1891
|
|
1565
|
-
def OnManageVectors(self, event):
|
1566
1892
|
if self.mapviewer is not None:
|
1567
1893
|
if self.mapviewer.linked:
|
1568
1894
|
if self.mapviewer.link_shareopsvect:
|
@@ -1572,7 +1898,9 @@ class Ops_Array(wx.Frame):
|
|
1572
1898
|
|
1573
1899
|
self.myzones.showstructure()
|
1574
1900
|
|
1575
|
-
def OnLoadvec(self, event):
|
1901
|
+
def OnLoadvec(self, event:wx.MouseEvent):
|
1902
|
+
""" Load vector file """
|
1903
|
+
|
1576
1904
|
dlg = wx.FileDialog(None, 'Select file',
|
1577
1905
|
wildcard='Vec file (*.vec)|*.vec|Vecz file (*.vecz)|*.vecz|Dxf file (*.dxf)|*.dxf|All (*.*)|*.*', style=wx.FD_OPEN)
|
1578
1906
|
|
@@ -1585,15 +1913,18 @@ class Ops_Array(wx.Frame):
|
|
1585
1913
|
dlg.Destroy()
|
1586
1914
|
self.myzones = Zones(self.fnsave, parent=self)
|
1587
1915
|
|
1916
|
+
# Link the same vector manager to all the linked arrays
|
1917
|
+
#FIXME : only works if the active_array is the good one
|
1588
1918
|
if self.mapviewer is not None:
|
1589
1919
|
if self.mapviewer.linked:
|
1590
1920
|
if not self.mapviewer.linkedList is None:
|
1591
|
-
for
|
1592
|
-
if
|
1593
|
-
|
1594
|
-
|
1921
|
+
for curViewer in self.mapviewer.linkedList:
|
1922
|
+
if curViewer.link_shareopsvect:
|
1923
|
+
curViewer.active_array.myops.myzones = self.myzones
|
1924
|
+
curViewer.active_array.myops.fnsave = self.fnsave
|
1595
1925
|
|
1596
|
-
def OnSaveasvec(self, event):
|
1926
|
+
def OnSaveasvec(self, event:wx.MouseEvent):
|
1927
|
+
""" Save vector file """
|
1597
1928
|
|
1598
1929
|
dlg = wx.FileDialog(None, 'Select file', wildcard='Vec file (*.vec)|*.vec|Vecz file (*.vecz)|*.vecz|All (*.*)|*.*', style=wx.FD_SAVE)
|
1599
1930
|
|
@@ -1607,49 +1938,64 @@ class Ops_Array(wx.Frame):
|
|
1607
1938
|
|
1608
1939
|
self.myzones.saveas(self.fnsave)
|
1609
1940
|
|
1941
|
+
# Link the same vector manager to all the linked arrays
|
1942
|
+
#FIXME : only works if the active_array is the good one
|
1610
1943
|
if self.mapviewer is not None:
|
1611
1944
|
if self.mapviewer.linked:
|
1612
1945
|
if not self.mapviewer.linkedList is None:
|
1613
|
-
for
|
1614
|
-
if
|
1615
|
-
|
1616
|
-
|
1617
|
-
def OnSavevec(self, event):
|
1946
|
+
for curViewer in self.mapviewer.linkedList:
|
1947
|
+
if curViewer.link_shareopsvect:
|
1948
|
+
curViewer.active_array.myops.fnsave = self.fnsave
|
1618
1949
|
|
1950
|
+
def OnSavevec(self, event:wx.MouseEvent):
|
1951
|
+
""" Save vector file """
|
1619
1952
|
if self.fnsave == '':
|
1620
1953
|
return
|
1621
1954
|
|
1622
1955
|
self.myzones.saveas(self.fnsave)
|
1623
1956
|
|
1624
1957
|
def select_node_by_node(self):
|
1958
|
+
"""
|
1959
|
+
Select nodes by individual clicks
|
1960
|
+
|
1961
|
+
Set the right action in the mapviewer who will attend the clicks
|
1962
|
+
"""
|
1963
|
+
|
1625
1964
|
if self.mapviewer is not None:
|
1626
1965
|
self.mapviewer.action = 'select node by node'
|
1627
1966
|
self.mapviewer.active_array = self.parentarray
|
1628
1967
|
|
1629
1968
|
def select_zone_inside_manager(self):
|
1969
|
+
"""
|
1970
|
+
Select nodes inside the active zone (manager)
|
1971
|
+
"""
|
1630
1972
|
|
1631
1973
|
if self.active_zone is None:
|
1632
|
-
|
1974
|
+
logging.warning(_('Please select an active zone !'))
|
1633
1975
|
return
|
1634
1976
|
|
1635
1977
|
for curvec in self.active_zone.myvectors:
|
1636
1978
|
self._select_vector_inside_manager(curvec)
|
1637
1979
|
|
1638
1980
|
def select_vector_inside_manager(self):
|
1981
|
+
"""
|
1982
|
+
Select nodes inside the active vector (manager)
|
1983
|
+
"""
|
1639
1984
|
if self.active_vector is None:
|
1640
|
-
|
1985
|
+
logging.warning(_('Please select an active vector !'))
|
1641
1986
|
return
|
1642
1987
|
|
1643
1988
|
self._select_vector_inside_manager(self.active_vector)
|
1644
1989
|
|
1645
1990
|
def _select_vector_inside_manager(self, vect: vector):
|
1991
|
+
""" Select nodes inside a vector or set action to add vertices to a vector by clicks"""
|
1646
1992
|
|
1647
|
-
if
|
1993
|
+
if vect.nbvertices > 2:
|
1648
1994
|
self.parentarray.mngselection.select_insidepoly(vect)
|
1649
1995
|
|
1650
1996
|
elif self.mapviewer is not None:
|
1651
|
-
if
|
1652
|
-
|
1997
|
+
if vect.nbvertices < 3:
|
1998
|
+
logging.info(_('Please add points to vector !'))
|
1653
1999
|
|
1654
2000
|
self.mapviewer.action = 'select by vector inside'
|
1655
2001
|
self.mapviewer.active_array = self.parentarray
|
@@ -1659,6 +2005,7 @@ class Ops_Array(wx.Frame):
|
|
1659
2005
|
self.vectmp.add_vertex(firstvert)
|
1660
2006
|
|
1661
2007
|
def select_zone_under_manager(self):
|
2008
|
+
""" Select nodes along the active zone (manager) """
|
1662
2009
|
|
1663
2010
|
if self.active_zone is None:
|
1664
2011
|
wx.MessageBox('Please select an active zone !')
|
@@ -1668,6 +2015,7 @@ class Ops_Array(wx.Frame):
|
|
1668
2015
|
self._select_vector_under_manager(curvec)
|
1669
2016
|
|
1670
2017
|
def select_vector_under_manager(self):
|
2018
|
+
""" Select nodes along the active vector (manager) """
|
1671
2019
|
if self.active_vector is None:
|
1672
2020
|
wx.MessageBox('Please select an active vector !')
|
1673
2021
|
return
|
@@ -1675,15 +2023,16 @@ class Ops_Array(wx.Frame):
|
|
1675
2023
|
self._select_vector_under_manager(self.active_vector)
|
1676
2024
|
|
1677
2025
|
def _select_vector_under_manager(self, vect: vector):
|
2026
|
+
""" Select nodes along a vector or set action to add vertices to a vector by clicks """
|
1678
2027
|
|
1679
|
-
if
|
2028
|
+
if vect.nbvertices > 1:
|
1680
2029
|
self.parentarray.mngselection.select_underpoly(vect)
|
1681
2030
|
|
1682
2031
|
elif self.mapviewer is not None:
|
1683
|
-
if
|
1684
|
-
|
2032
|
+
if vect.nbvertices < 2:
|
2033
|
+
logging.info(_('Please add points to vector by clicks !'))
|
1685
2034
|
|
1686
|
-
self.mapviewer.action = 'select by vector
|
2035
|
+
self.mapviewer.action = 'select by vector along'
|
1687
2036
|
self.mapviewer.active_array = self.parentarray
|
1688
2037
|
self.Active_vector(vect)
|
1689
2038
|
|
@@ -1691,7 +2040,10 @@ class Ops_Array(wx.Frame):
|
|
1691
2040
|
self.vectmp.add_vertex(firstvert)
|
1692
2041
|
|
1693
2042
|
def select_vector_inside_tmp(self):
|
2043
|
+
""" Select nodes inside the temporary vector """
|
2044
|
+
|
1694
2045
|
if self.mapviewer is not None:
|
2046
|
+
logging.info(_('Please add points to vector by clicks !'))
|
1695
2047
|
self.mapviewer.action = 'select by tmp vector inside'
|
1696
2048
|
self.vectmp.reset()
|
1697
2049
|
self.Active_vector(self.vectmp)
|
@@ -1701,8 +2053,10 @@ class Ops_Array(wx.Frame):
|
|
1701
2053
|
self.vectmp.add_vertex(firstvert)
|
1702
2054
|
|
1703
2055
|
def select_vector_under_tmp(self):
|
2056
|
+
""" Select nodes along the temporary vector """
|
1704
2057
|
if self.mapviewer is not None:
|
1705
|
-
|
2058
|
+
logging.info(_('Please add points to vector by clicks !'))
|
2059
|
+
self.mapviewer.action = 'select by tmp vector along'
|
1706
2060
|
self.vectmp.reset()
|
1707
2061
|
self.Active_vector(self.vectmp)
|
1708
2062
|
self.mapviewer.active_array = self.parentarray
|
@@ -1710,7 +2064,9 @@ class Ops_Array(wx.Frame):
|
|
1710
2064
|
firstvert = wolfvertex(0., 0.)
|
1711
2065
|
self.vectmp.add_vertex(firstvert)
|
1712
2066
|
|
1713
|
-
def OnLaunchSelect(self, event):
|
2067
|
+
def OnLaunchSelect(self, event:wx.MouseEvent):
|
2068
|
+
""" Action button """
|
2069
|
+
|
1714
2070
|
id = self.selectmethod.GetSelection()
|
1715
2071
|
|
1716
2072
|
if id == 0:
|
@@ -1732,23 +2088,24 @@ class Ops_Array(wx.Frame):
|
|
1732
2088
|
logging.info(_(''))
|
1733
2089
|
self.select_vector_inside_tmp()
|
1734
2090
|
elif id == 4:
|
1735
|
-
logging.info(_('Node selection
|
2091
|
+
logging.info(_('Node selection along active vector (manager)'))
|
1736
2092
|
self.select_vector_under_manager()
|
1737
2093
|
elif id == 5:
|
1738
|
-
logging.info(_('Node selection
|
2094
|
+
logging.info(_('Node selection along active zone (manager)'))
|
1739
2095
|
self.select_zone_under_manager()
|
1740
2096
|
elif id == 6:
|
1741
|
-
logging.info(_('Node selection
|
2097
|
+
logging.info(_('Node selection along temporary vector'))
|
1742
2098
|
logging.info(_(''))
|
1743
2099
|
logging.info(_(' Choose vector by clicks...'))
|
1744
2100
|
logging.info(_(''))
|
1745
2101
|
self.select_vector_under_tmp()
|
1746
2102
|
|
1747
|
-
def onclose(self, event):
|
2103
|
+
def onclose(self, event:wx.MouseEvent):
|
2104
|
+
""" Hide the window """
|
1748
2105
|
self.Hide()
|
1749
2106
|
|
1750
|
-
def onshow(self, event):
|
1751
|
-
|
2107
|
+
def onshow(self, event:wx.MouseEvent):
|
2108
|
+
""" Show the window - set string with null value and update palette """
|
1752
2109
|
if self.parentarray.nullvalue == np.nan:
|
1753
2110
|
self.txt_nullval.Value = 'nan'
|
1754
2111
|
else :
|
@@ -1756,7 +2113,9 @@ class Ops_Array(wx.Frame):
|
|
1756
2113
|
|
1757
2114
|
self.update_palette()
|
1758
2115
|
|
1759
|
-
def Active_vector(self, vect: vector, copyall=True):
|
2116
|
+
def Active_vector(self, vect: vector, copyall:bool=True):
|
2117
|
+
""" Set the active vector to vect and forward to mapviewer """
|
2118
|
+
|
1760
2119
|
if vect is None:
|
1761
2120
|
return
|
1762
2121
|
self.active_vector = vect
|
@@ -1768,24 +2127,33 @@ class Ops_Array(wx.Frame):
|
|
1768
2127
|
if self.mapviewer is not None and copyall:
|
1769
2128
|
self.mapviewer.Active_vector(vect)
|
1770
2129
|
|
1771
|
-
def Active_zone(self, zone):
|
1772
|
-
|
2130
|
+
def Active_zone(self, target_zone:zone):
|
2131
|
+
""" Set the active zone to target_zone and forward to mapviewer """
|
2132
|
+
self.active_zone = target_zone
|
1773
2133
|
if self.mapviewer is not None:
|
1774
|
-
self.mapviewer.Active_zone(
|
2134
|
+
self.mapviewer.Active_zone(target_zone)
|
1775
2135
|
|
1776
2136
|
def update_palette(self):
|
2137
|
+
"""
|
2138
|
+
Update palette
|
2139
|
+
|
2140
|
+
Redraw the palette with Matplotlib and fill the grid with the values and RGB components
|
2141
|
+
"""
|
1777
2142
|
self.Palette.add_ax()
|
1778
2143
|
fig, ax = self.Palette.get_fig_ax()
|
1779
2144
|
self.parentarray.mypal.plot(fig, ax)
|
1780
2145
|
fig.canvas.draw()
|
1781
2146
|
self.parentarray.mypal.fillgrid(self.palgrid)
|
1782
2147
|
|
1783
|
-
def Onsavepal(self, event):
|
2148
|
+
def Onsavepal(self, event:wx.MouseEvent):
|
2149
|
+
""" Save palette to file """
|
2150
|
+
|
1784
2151
|
myarray: WolfArray
|
1785
2152
|
myarray = self.parentarray
|
1786
2153
|
myarray.mypal.savefile()
|
1787
2154
|
|
1788
|
-
def Onloadpal(self, event):
|
2155
|
+
def Onloadpal(self, event:wx.MouseEvent):
|
2156
|
+
""" Load palette from file """
|
1789
2157
|
myarray: WolfArray
|
1790
2158
|
myarray = self.parentarray
|
1791
2159
|
myarray.mypal.readfile()
|
@@ -1793,17 +2161,16 @@ class Ops_Array(wx.Frame):
|
|
1793
2161
|
myarray.mypal.automatic = False
|
1794
2162
|
self.palauto.SetValue(0)
|
1795
2163
|
|
1796
|
-
|
1797
|
-
# myarray.updatepalette(0)
|
1798
|
-
# myarray.delete_lists()
|
1799
|
-
self.update_palette()
|
2164
|
+
self.refresh_array()
|
1800
2165
|
|
1801
|
-
def Onpalimage(self, event):
|
2166
|
+
def Onpalimage(self, event:wx.MouseEvent):
|
2167
|
+
""" Create image from palette """
|
1802
2168
|
myarray: WolfArray
|
1803
2169
|
myarray = self.parentarray
|
1804
2170
|
myarray.mypal.export_image()
|
1805
2171
|
|
1806
|
-
def Onpaldistribute(self, event):
|
2172
|
+
def Onpaldistribute(self, event:wx.MouseEvent):
|
2173
|
+
""" Distribute values in palette """
|
1807
2174
|
myarray: WolfArray
|
1808
2175
|
myarray = self.parentarray
|
1809
2176
|
myarray.mypal.distribute_values()
|
@@ -1811,12 +2178,10 @@ class Ops_Array(wx.Frame):
|
|
1811
2178
|
myarray.mypal.automatic = False
|
1812
2179
|
self.palauto.SetValue(0)
|
1813
2180
|
|
1814
|
-
|
1815
|
-
# myarray.updatepalette(0)
|
1816
|
-
# myarray.delete_lists()
|
1817
|
-
self.update_palette()
|
2181
|
+
self.refresh_array()
|
1818
2182
|
|
1819
|
-
def Onupdatepal(self, event):
|
2183
|
+
def Onupdatepal(self, event:wx.MouseEvent):
|
2184
|
+
""" Apply options to palette """
|
1820
2185
|
curarray: WolfArray
|
1821
2186
|
curarray = self.parentarray
|
1822
2187
|
|
@@ -1860,10 +2225,10 @@ class Ops_Array(wx.Frame):
|
|
1860
2225
|
curarray.shading = True
|
1861
2226
|
|
1862
2227
|
if dellists:
|
1863
|
-
|
1864
|
-
# curarray.delete_lists()
|
2228
|
+
self.refresh_array()
|
1865
2229
|
|
1866
2230
|
def OnClickHistoUpdate(self, event: wx.Event):
|
2231
|
+
""" Create a histogram of the current array """
|
1867
2232
|
|
1868
2233
|
itemlabel = event.GetEventObject().GetLabel()
|
1869
2234
|
fig, ax = self.histo.get_fig_ax()
|
@@ -1888,7 +2253,8 @@ class Ops_Array(wx.Frame):
|
|
1888
2253
|
|
1889
2254
|
fig.canvas.draw()
|
1890
2255
|
|
1891
|
-
def OnClickColorPal(self, event):
|
2256
|
+
def OnClickColorPal(self, event: wx.Event):
|
2257
|
+
""" Edit color of a palette item """
|
1892
2258
|
|
1893
2259
|
gridto = self.palgrid
|
1894
2260
|
k = gridto.GetGridCursorRow()
|
@@ -1920,51 +2286,71 @@ class Ops_Array(wx.Frame):
|
|
1920
2286
|
|
1921
2287
|
class SelectionData():
|
1922
2288
|
"""
|
1923
|
-
|
2289
|
+
User-selected data in a WolfArray
|
1924
2290
|
|
1925
|
-
|
1926
|
-
- myselection (list)
|
1927
|
-
- selections( dict)
|
1928
|
-
|
2291
|
+
Contains two storage elements :
|
2292
|
+
- myselection (list): Current selection which will be lost in the event of a reset
|
2293
|
+
- selections( dict): Stored selection(s) to be used, for example, in a spatial interpolation operation.
|
2294
|
+
These selections are only lost in the event of a general reset.
|
1929
2295
|
|
1930
|
-
|
2296
|
+
The selected nodes are stored using their "world" spatial coordinates so that they can be easily transferred to other objects.
|
1931
2297
|
"""
|
1932
|
-
myselection:
|
1933
|
-
selections: dict
|
2298
|
+
myselection:list[tuple[float, float]]
|
2299
|
+
selections: dict[str:dict['select':list[tuple[float, float]], 'idgllist':int, 'color':list[float]]]
|
1934
2300
|
|
1935
|
-
def __init__(self, parent) -> None:
|
2301
|
+
def __init__(self, parent:"WolfArray") -> None:
|
1936
2302
|
self.parent: WolfArray
|
1937
2303
|
self.parent = parent
|
1938
2304
|
|
2305
|
+
#copy of the resolution
|
1939
2306
|
self.dx = parent.dx
|
1940
2307
|
self.dy = parent.dy
|
1941
2308
|
|
1942
2309
|
self.myselection = []
|
1943
2310
|
self.selections = {}
|
1944
|
-
|
2311
|
+
|
2312
|
+
self.update_plot_selection = False # force to update OpenGL list if True
|
1945
2313
|
self.hideselection = False
|
1946
|
-
self.numlist_select = 0
|
2314
|
+
self.numlist_select = 0 # OpenGL list index
|
1947
2315
|
|
1948
|
-
def move_selectionto(self, idx, color):
|
1949
|
-
"""
|
2316
|
+
def move_selectionto(self, idx:str, color:list[float]):
|
2317
|
+
"""
|
2318
|
+
Transfer current selection to dictionary
|
2319
|
+
|
2320
|
+
:param idx: id/key of the selection
|
2321
|
+
:param color: color of the selection - list of 3 floats between 0 and 255
|
2322
|
+
"""
|
2323
|
+
|
2324
|
+
assert len(color) == 3, "color must be a list of 3 floats between 0 and 255"
|
2325
|
+
|
2326
|
+
# force idx to be a string
|
1950
2327
|
idtxt = str(idx)
|
1951
2328
|
self.selections[idtxt] = {}
|
1952
2329
|
curdict = self.selections[idtxt]
|
1953
2330
|
|
1954
2331
|
curdict['select'] = self.myselection
|
1955
|
-
curdict['idgllist'] = 0
|
1956
|
-
self.myselection = []
|
1957
|
-
self.update_nb_nodes_sections()
|
2332
|
+
curdict['idgllist'] = 0 # will be created later - index of OpenGL list
|
1958
2333
|
curdict['color'] = color
|
1959
2334
|
|
2335
|
+
self.myselection = [] # reset current selection
|
2336
|
+
self.update_nb_nodes_sections()
|
2337
|
+
|
1960
2338
|
def plot_selection(self):
|
2339
|
+
""" Plot current selection and stored selections """
|
1961
2340
|
|
2341
|
+
# Make a copy of the current value of the flag because it will be modified in the function _plot_selection
|
2342
|
+
# So, if we want to update the plot, we need to apply the flag on each selection (current ans stored)
|
1962
2343
|
update_select = self.update_plot_selection
|
2344
|
+
|
1963
2345
|
if self.myselection != 'all':
|
2346
|
+
# plot current selection in RED if not 'all'
|
1964
2347
|
if len(self.myselection) > 0:
|
1965
|
-
self.numlist_select = self._plot_selection(self.myselection,
|
2348
|
+
self.numlist_select = self._plot_selection(self.myselection,
|
2349
|
+
(1., 0., 0.),
|
2350
|
+
self.numlist_select)
|
1966
2351
|
|
1967
2352
|
if len(self.selections) > 0:
|
2353
|
+
# plot stored selections
|
1968
2354
|
for cur in self.selections.values():
|
1969
2355
|
if cur['select'] != 'all':
|
1970
2356
|
self.update_plot_selection = update_select
|
@@ -1974,8 +2360,16 @@ class SelectionData():
|
|
1974
2360
|
float(col[2]) / 255.),
|
1975
2361
|
cur['idgllist'])
|
1976
2362
|
|
1977
|
-
def _plot_selection(self, curlist, color, loclist=0):
|
2363
|
+
def _plot_selection(self, curlist:list[float], color:list[float], loclist:int=0):
|
2364
|
+
"""
|
2365
|
+
Plot a selection
|
2366
|
+
|
2367
|
+
:param curlist: list of selected nodes -- list of tuples (x,y)
|
2368
|
+
:param color: color of the selection - list of 3 floats between 0 and 1
|
2369
|
+
:param loclist: index of OpenGL list
|
2370
|
+
"""
|
1978
2371
|
|
2372
|
+
#FIXME : Is it a good idea to use SHADER rather than list ?
|
1979
2373
|
if self.update_plot_selection:
|
1980
2374
|
if loclist != 0:
|
1981
2375
|
glDeleteLists(loclist, 1)
|
@@ -2020,22 +2414,41 @@ class SelectionData():
|
|
2020
2414
|
|
2021
2415
|
return loclist
|
2022
2416
|
|
2023
|
-
def add_node_to_selection(self, x, y, verif=True):
|
2024
|
-
"""
|
2417
|
+
def add_node_to_selection(self, x:float, y:float, verif:bool=True):
|
2418
|
+
"""
|
2419
|
+
Add one coordinate to the selection
|
2420
|
+
|
2421
|
+
:param x: x coordinate
|
2422
|
+
:param y: y coordinate
|
2423
|
+
:param verif: if True, the coordinates are checked to avoid duplicates
|
2424
|
+
"""
|
2425
|
+
|
2025
2426
|
# on repasse par les i,j car les coordonnées transférées peuvent venir d'un click souris
|
2026
2427
|
# le but est de ne conserver que les coordonnées des CG de mailles
|
2027
2428
|
i, j = self.parent.get_ij_from_xy(x, y)
|
2028
2429
|
self.add_node_to_selectionij(i, j, verif)
|
2029
2430
|
|
2030
|
-
def add_nodes_to_selection(self, xy, verif=True):
|
2031
|
-
"""
|
2431
|
+
def add_nodes_to_selection(self, xy:list[float], verif:bool=True):
|
2432
|
+
"""
|
2433
|
+
Add multiple coordinates to the selection
|
2434
|
+
|
2435
|
+
:param xy: list of coordinates
|
2436
|
+
:param verif: if True, the coordinates are checked to avoid duplicates
|
2437
|
+
"""
|
2438
|
+
|
2032
2439
|
# on repasse par les i,j car les coordonnées transférées peuvent venir d'un click souris
|
2033
2440
|
# le but est de ne conserver que les coordonnées des CG de mailles
|
2034
2441
|
ij = [self.parent.get_ij_from_xy(x, y) for x, y in xy]
|
2035
2442
|
self.add_nodes_to_selectionij(ij, verif)
|
2036
2443
|
|
2037
|
-
def add_node_to_selectionij(self, i, j, verif=True):
|
2038
|
-
"""
|
2444
|
+
def add_node_to_selectionij(self, i:int, j:int, verif=True):
|
2445
|
+
"""
|
2446
|
+
Add one ij coordinate to the selection
|
2447
|
+
|
2448
|
+
:param i: i coordinate
|
2449
|
+
:param j: j coordinate
|
2450
|
+
:param verif: if True, the coordinates are checked to avoid duplicates
|
2451
|
+
"""
|
2039
2452
|
x1, y1 = self.parent.get_xy_from_ij(i, j)
|
2040
2453
|
|
2041
2454
|
if verif:
|
@@ -2050,8 +2463,14 @@ class SelectionData():
|
|
2050
2463
|
else:
|
2051
2464
|
self.myselection.append((x1, y1))
|
2052
2465
|
|
2053
|
-
def add_nodes_to_selectionij(self, ij, verif=True):
|
2054
|
-
"""
|
2466
|
+
def add_nodes_to_selectionij(self, ij:list[tuple[float, float]], verif:bool=True):
|
2467
|
+
"""
|
2468
|
+
Add multiple ij coordinates to the selection
|
2469
|
+
|
2470
|
+
:param ij: list of ij coordinates
|
2471
|
+
:param verif: if True, the coordinates are checked to avoid duplicates
|
2472
|
+
"""
|
2473
|
+
|
2055
2474
|
if len(ij)==0:
|
2056
2475
|
logging.info(_('Nothing to do in add_nodes_to_selectionij !'))
|
2057
2476
|
return
|
@@ -2081,6 +2500,7 @@ class SelectionData():
|
|
2081
2500
|
self.myselection = np.unique(self.myselection, axis=0)
|
2082
2501
|
|
2083
2502
|
def select_insidepoly(self, myvect: vector):
|
2503
|
+
""" Select nodes inside a polygon """
|
2084
2504
|
|
2085
2505
|
nbini = len(self.myselection)
|
2086
2506
|
|
@@ -2100,6 +2520,7 @@ class SelectionData():
|
|
2100
2520
|
self.update_nb_nodes_sections()
|
2101
2521
|
|
2102
2522
|
def select_underpoly(self, myvect: vector):
|
2523
|
+
""" Select nodes along a polyline """
|
2103
2524
|
|
2104
2525
|
nbini = len(self.myselection)
|
2105
2526
|
|
@@ -2147,6 +2568,29 @@ class SelectionData():
|
|
2147
2568
|
array = self.parent.array
|
2148
2569
|
nbini = len(self.myselection)
|
2149
2570
|
|
2571
|
+
if array.dtype == np.float32:
|
2572
|
+
condval = np.float32(condval)
|
2573
|
+
condval2 = np.float32(condval2)
|
2574
|
+
elif array.dtype == np.float64:
|
2575
|
+
condval = np.float64(condval)
|
2576
|
+
condval2 = np.float64(condval2)
|
2577
|
+
elif array.dtype == np.int32:
|
2578
|
+
condval = np.int32(condval)
|
2579
|
+
condval2 = np.int32(condval2)
|
2580
|
+
elif array.dtype == np.int64:
|
2581
|
+
condval = np.int64(condval)
|
2582
|
+
condval2 = np.int64(condval2)
|
2583
|
+
elif array.dtype == np.int16:
|
2584
|
+
condval = np.int16(condval)
|
2585
|
+
condval2 = np.int16(condval2)
|
2586
|
+
elif array.dtype == np.int8:
|
2587
|
+
condval = np.int8(condval)
|
2588
|
+
condval2 = np.int8(condval2)
|
2589
|
+
else:
|
2590
|
+
logging.error(_('Unknown dtype in treat_select !'))
|
2591
|
+
return
|
2592
|
+
|
2593
|
+
|
2150
2594
|
if usemask :
|
2151
2595
|
mask=np.logical_not(array.mask)
|
2152
2596
|
if nbini == 0:
|
@@ -2310,6 +2754,29 @@ class SelectionData():
|
|
2310
2754
|
return np.isnan(val)
|
2311
2755
|
|
2312
2756
|
array = self.parent.array
|
2757
|
+
|
2758
|
+
if array.dtype == np.float32:
|
2759
|
+
opval = np.float32(opval)
|
2760
|
+
condval = np.float32(condval)
|
2761
|
+
elif array.dtype == np.float64:
|
2762
|
+
opval = np.float64(opval)
|
2763
|
+
condval = np.float64(condval)
|
2764
|
+
elif array.dtype == np.int32:
|
2765
|
+
opval = np.int32(opval)
|
2766
|
+
condval = np.int32(condval)
|
2767
|
+
elif array.dtype == np.int64:
|
2768
|
+
opval = np.int64(opval)
|
2769
|
+
condval = np.int64(condval)
|
2770
|
+
elif array.dtype == np.int16:
|
2771
|
+
opval = np.int16(opval)
|
2772
|
+
condval = np.int16(condval)
|
2773
|
+
elif array.dtype == np.int8:
|
2774
|
+
opval = np.int8(opval)
|
2775
|
+
condval = np.int8(condval)
|
2776
|
+
else:
|
2777
|
+
logging.error(_('Unknown dtype in treat_select !'))
|
2778
|
+
return
|
2779
|
+
|
2313
2780
|
if self.myselection == 'all':
|
2314
2781
|
if op == 0:
|
2315
2782
|
if cond == 0:
|
@@ -2437,6 +2904,10 @@ class SelectionData():
|
|
2437
2904
|
ind = np.argwhere(np.logical_and(np.isnan(array), np.logical_not(array.mask)))
|
2438
2905
|
array[ind[:, 0], ind[:, 1]] = opval
|
2439
2906
|
else:
|
2907
|
+
if len(self.myselection) == 0:
|
2908
|
+
logging.info(_('Nothing to do in treat_select ! -- PLease select some nodes'))
|
2909
|
+
return
|
2910
|
+
|
2440
2911
|
ij = [self.parent.get_ij_from_xy(cur[0], cur[1]) for cur in self.myselection]
|
2441
2912
|
|
2442
2913
|
if op == 0:
|
@@ -2461,9 +2932,13 @@ class SelectionData():
|
|
2461
2932
|
array.data[i, j] = opval
|
2462
2933
|
|
2463
2934
|
self.parent.mask_data(self.parent.nullvalue)
|
2935
|
+
|
2936
|
+
self.refresh_parantarray()
|
2937
|
+
|
2938
|
+
def refresh_parantarray(self):
|
2939
|
+
""" Refresh the parent array after a selection """
|
2940
|
+
|
2464
2941
|
self.parent.reset_plot()
|
2465
|
-
if self.parent.mapviewer is not None:
|
2466
|
-
self.parent.mapviewer.Refresh()
|
2467
2942
|
|
2468
2943
|
def mask_condition(self, op, cond, opval, condval):
|
2469
2944
|
# operationChoices = [ u"+", u"-", u"*", u"/", u"replace'" ]
|
@@ -2483,6 +2958,29 @@ class SelectionData():
|
|
2483
2958
|
return np.isnan(val)
|
2484
2959
|
|
2485
2960
|
array = self.parent.array
|
2961
|
+
|
2962
|
+
if array.dtype == np.float32:
|
2963
|
+
opval = np.float32(opval)
|
2964
|
+
condval = np.float32(condval)
|
2965
|
+
elif array.dtype == np.float64:
|
2966
|
+
opval = np.float64(opval)
|
2967
|
+
condval = np.float64(condval)
|
2968
|
+
elif array.dtype == np.int32:
|
2969
|
+
opval = np.int32(opval)
|
2970
|
+
condval = np.int32(condval)
|
2971
|
+
elif array.dtype == np.int64:
|
2972
|
+
opval = np.int64(opval)
|
2973
|
+
condval = np.int64(condval)
|
2974
|
+
elif array.dtype == np.int16:
|
2975
|
+
opval = np.int16(opval)
|
2976
|
+
condval = np.int16(condval)
|
2977
|
+
elif array.dtype == np.int8:
|
2978
|
+
opval = np.int8(opval)
|
2979
|
+
condval = np.int8(condval)
|
2980
|
+
else:
|
2981
|
+
logging.error(_('Unknown dtype in treat_select !'))
|
2982
|
+
return
|
2983
|
+
|
2486
2984
|
if self.myselection == 'all':
|
2487
2985
|
if cond == 0:
|
2488
2986
|
# <
|
@@ -2553,8 +3051,6 @@ class SelectionData():
|
|
2553
3051
|
myhead.nbx = int((ex - myhead.origx) / array.dx)
|
2554
3052
|
myhead.nby = int((ey - myhead.origy) / array.dy)
|
2555
3053
|
|
2556
|
-
myhead.nbdims=2
|
2557
|
-
|
2558
3054
|
return myhead
|
2559
3055
|
|
2560
3056
|
def get_newarray(self):
|
@@ -2613,7 +3109,8 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
2613
3109
|
srcheader=None, # initialize dimension from header_wolf instance
|
2614
3110
|
idx:str = '', # indentity --> required by the mapviewer
|
2615
3111
|
plotted:bool = False, # True = will be plotted if required by the mapviewer
|
2616
|
-
need_for_wx:bool = False
|
3112
|
+
need_for_wx:bool = False, # True = a wxApp is required (if no application is underway --> Error)
|
3113
|
+
mask_source:np.ndarray = None, # mask to link to the data
|
2617
3114
|
) -> None:
|
2618
3115
|
|
2619
3116
|
Element_To_Draw.__init__(self, idx, plotted, mapviewer, need_for_wx)
|
@@ -2629,7 +3126,6 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
2629
3126
|
self.linkedarrays = []
|
2630
3127
|
|
2631
3128
|
self.filename = ''
|
2632
|
-
self.nbdims = 2
|
2633
3129
|
self.isblock = False
|
2634
3130
|
self.blockindex = 0
|
2635
3131
|
self.wolftype = whichtype
|
@@ -2686,17 +3182,22 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
2686
3182
|
|
2687
3183
|
self.head_blocks = header.head_blocks.copy()
|
2688
3184
|
|
2689
|
-
|
2690
|
-
|
3185
|
+
self.allocate_ressources()
|
3186
|
+
|
3187
|
+
# # FIXME Why not initialize with nullvalue ?
|
3188
|
+
# self.array = ma.MaskedArray(np.ones((self.nbx, self.nby), order='F', dtype=self.dtype))
|
2691
3189
|
|
2692
3190
|
if fname is not None:
|
2693
|
-
|
3191
|
+
|
3192
|
+
self.filename = str(fname)
|
2694
3193
|
self.read_all()
|
2695
|
-
|
3194
|
+
|
3195
|
+
if mask_source is not None:
|
3196
|
+
self.copy_mask_log(mask_source)
|
3197
|
+
elif masknull and self.preload:
|
2696
3198
|
self.mask_data(self.nullvalue)
|
2697
3199
|
|
2698
3200
|
elif mold is not None:
|
2699
|
-
self.nbdims = mold.nbdims
|
2700
3201
|
self.nbx = mold.nbx
|
2701
3202
|
self.nby = mold.nby
|
2702
3203
|
self.nbz = mold.nbz
|
@@ -2726,12 +3227,11 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
2726
3227
|
self.add_ops_sel() # Ajout d'un gestionnaire de sélection et d'opérations
|
2727
3228
|
|
2728
3229
|
def show_properties(self):
|
2729
|
-
""" Affichage des propriétés de la matrice """
|
3230
|
+
""" Affichage des propriétés de la matrice dans une fenêtre wxPython """
|
2730
3231
|
if self.wx_exists and self.myops is not None:
|
2731
3232
|
self.myops.SetTitle(_('Operations on array: ') + self.idx)
|
2732
3233
|
self.myops.Show()
|
2733
3234
|
|
2734
|
-
|
2735
3235
|
@property
|
2736
3236
|
def dtype(self):
|
2737
3237
|
"""
|
@@ -2763,6 +3263,14 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
2763
3263
|
return dtype
|
2764
3264
|
|
2765
3265
|
def loadnap_and_apply(self):
|
3266
|
+
"""
|
3267
|
+
Load a mask file (aka nap) and apply it to the array;
|
3268
|
+
|
3269
|
+
The mask values are set to the nullvalue.
|
3270
|
+
|
3271
|
+
The mask file must have the same name as the array file, with the extension .napbin.
|
3272
|
+
It is useful for 2D WOLF simulations.
|
3273
|
+
"""
|
2766
3274
|
|
2767
3275
|
file_name, file_extension = os.path.splitext(self.filename)
|
2768
3276
|
fnnap = file_name + '.napbin'
|
@@ -2772,8 +3280,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
2772
3280
|
self.array.data[np.where(locnap.array.mask)] = self.nullvalue
|
2773
3281
|
self.mask_data(self.nullvalue)
|
2774
3282
|
|
2775
|
-
|
2776
|
-
self.reset_plot()
|
3283
|
+
self.reset_plot()
|
2777
3284
|
|
2778
3285
|
def add_crosslinked_array(self, newlink:"WolfArray"):
|
2779
3286
|
"""Ajout d'une matrice liée croisée"""
|
@@ -2796,17 +3303,19 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
2796
3303
|
if self.linkedvec is not None:
|
2797
3304
|
self.mask_outsidepoly(self.linkedvec)
|
2798
3305
|
|
2799
|
-
|
2800
|
-
self.reset_plot()
|
3306
|
+
self.reset_plot()
|
2801
3307
|
|
2802
|
-
def export_geotif(self,outdir='',extent = ''):
|
3308
|
+
def export_geotif(self, outdir='', extent = ''):
|
2803
3309
|
"""
|
2804
|
-
Export de la matrice au format Geotiff
|
3310
|
+
Export de la matrice au format Geotiff (Lambert 72 - EPSG:31370)
|
2805
3311
|
|
2806
3312
|
Formats supportés :
|
2807
3313
|
- Int32
|
2808
3314
|
- Float32
|
2809
3315
|
- Float64
|
3316
|
+
|
3317
|
+
:param outdir: directory
|
3318
|
+
:param extent: suffix to add to the filename before the extension '.tif'
|
2810
3319
|
"""
|
2811
3320
|
from osgeo import gdal, osr, gdalconst
|
2812
3321
|
|
@@ -2849,7 +3358,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
2849
3358
|
band.FlushCache()
|
2850
3359
|
band.ComputeStatistics(True)
|
2851
3360
|
|
2852
|
-
def import_geotif(self, fn:str='', which = None, crop=None):
|
3361
|
+
def import_geotif(self, fn:str='', which:int = None, crop:list[float]=None):
|
2853
3362
|
"""
|
2854
3363
|
Import de la matrice au format Geotiff
|
2855
3364
|
|
@@ -2857,6 +3366,10 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
2857
3366
|
- Int32
|
2858
3367
|
- Float32
|
2859
3368
|
- Float64
|
3369
|
+
|
3370
|
+
:param fn: filename
|
3371
|
+
:param which: band to import
|
3372
|
+
:param crop: crop the data - [xmin, xmax, ymin, ymax]
|
2860
3373
|
"""
|
2861
3374
|
from osgeo import gdal, osr, gdalconst
|
2862
3375
|
|
@@ -2968,7 +3481,13 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
2968
3481
|
def change_gui(self, newparentgui):
|
2969
3482
|
"""
|
2970
3483
|
Move GUI to another instance
|
3484
|
+
|
3485
|
+
:param newparentgui: WolfMapViewer instance
|
2971
3486
|
"""
|
3487
|
+
|
3488
|
+
from .PyDraw import WolfMapViewer
|
3489
|
+
assert isinstance(newparentgui, WolfMapViewer), _('newparentgui must be a WolfMapViewer instance')
|
3490
|
+
|
2972
3491
|
self.wx_exists = wx.App.Get() is not None
|
2973
3492
|
|
2974
3493
|
if self.mapviewer is None:
|
@@ -3020,7 +3539,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3020
3539
|
plt.show()
|
3021
3540
|
|
3022
3541
|
def compare_tri(self,mytri:Triangulation):
|
3023
|
-
|
3542
|
+
""" Graphique de comparaison des valeurs d'un nuage de points et des valeurs de la matrice sous les mêmes positions """
|
3024
3543
|
xyz_cloud = mytri.pts
|
3025
3544
|
zarray = np.array([self.get_value(curxy[0],curxy[1]) for curxy in xyz_cloud])
|
3026
3545
|
|
@@ -3055,7 +3574,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3055
3574
|
|
3056
3575
|
plt.show()
|
3057
3576
|
|
3058
|
-
def interpolate_on_cloud(self, xy, z, method='linear'):
|
3577
|
+
def interpolate_on_cloud(self, xy:np.ndarray, z:np.ndarray, method='linear'):
|
3059
3578
|
"""
|
3060
3579
|
See : https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html
|
3061
3580
|
|
@@ -3216,8 +3735,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3216
3735
|
self.reset_plot()
|
3217
3736
|
return
|
3218
3737
|
|
3219
|
-
def import_from_gltf(self, fn='', fnpos='', interp_method = 'matplotlib'):
|
3220
|
-
|
3738
|
+
def import_from_gltf(self, fn:str='', fnpos:str='', interp_method:Literal['matplotlib','numpy'] = 'matplotlib'):
|
3221
3739
|
"""
|
3222
3740
|
interp_method == 'matplotlib' or 'griddata'
|
3223
3741
|
"""
|
@@ -3274,7 +3792,13 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3274
3792
|
|
3275
3793
|
self.reset_plot()
|
3276
3794
|
|
3277
|
-
def export_to_gltf(self, bounds=None, fn=''):
|
3795
|
+
def export_to_gltf(self, bounds:list[float]=None, fn:str=''):
|
3796
|
+
"""
|
3797
|
+
Export to GLTF/GLB format
|
3798
|
+
|
3799
|
+
:param bounds: [[xmin,xmax],[ymin,ymax]]
|
3800
|
+
:param fn: filename
|
3801
|
+
"""
|
3278
3802
|
|
3279
3803
|
mytri, znull = self.get_triangulation(bounds)
|
3280
3804
|
mytri.export_to_gltf(fn)
|
@@ -3321,7 +3845,12 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3321
3845
|
f.write(str(bounds[1][1]) + '\n')
|
3322
3846
|
f.write(str(znull))
|
3323
3847
|
|
3324
|
-
def get_triangulation(self, bounds=None):
|
3848
|
+
def get_triangulation(self, bounds:list[float]=None):
|
3849
|
+
"""
|
3850
|
+
Traingulation of the array
|
3851
|
+
|
3852
|
+
:param bounds: [[xmin,xmax],[ymin,ymax]]
|
3853
|
+
"""
|
3325
3854
|
|
3326
3855
|
if bounds is None:
|
3327
3856
|
ox = self.origx + self.translx
|
@@ -3376,7 +3905,9 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3376
3905
|
mytri = Triangulation(pts = points, tri = triangles)
|
3377
3906
|
return mytri, znull
|
3378
3907
|
|
3379
|
-
def hillshade(self, azimuth, angle_altitude):
|
3908
|
+
def hillshade(self, azimuth:float, angle_altitude:float):
|
3909
|
+
""" Create a hillshade array """
|
3910
|
+
|
3380
3911
|
azimuth = 360.0 - azimuth
|
3381
3912
|
|
3382
3913
|
x, y = np.gradient(self.array)
|
@@ -3395,6 +3926,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3395
3926
|
self.shaded.delete_lists()
|
3396
3927
|
|
3397
3928
|
def get_gradient_norm(self):
|
3929
|
+
""" Compute and return the norm of the gradient """
|
3398
3930
|
|
3399
3931
|
mygradient = WolfArray(mold=self)
|
3400
3932
|
|
@@ -3405,6 +3937,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3405
3937
|
return mygradient
|
3406
3938
|
|
3407
3939
|
def get_laplace(self):
|
3940
|
+
""" Compute and return the laplacian """
|
3408
3941
|
mylap = WolfArray(mold=self)
|
3409
3942
|
mylap.array = ma.asarray(laplace(self.array) / self.dx ** 2.)
|
3410
3943
|
mylap.array.mask = self.array.mask
|
@@ -3412,6 +3945,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3412
3945
|
return mylap
|
3413
3946
|
|
3414
3947
|
def volume_estimation(self, axs=None):
|
3948
|
+
""" Estimation of the volume of the selected zone """
|
3415
3949
|
|
3416
3950
|
vect = self.array[np.logical_not(self.array.mask)].flatten()
|
3417
3951
|
zmin = np.amin(vect)
|
@@ -3534,7 +4068,9 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3534
4068
|
|
3535
4069
|
return axs
|
3536
4070
|
|
3537
|
-
def paste_all(self, fromarray):
|
4071
|
+
def paste_all(self, fromarray:"WolfArray"):
|
4072
|
+
""" Paste all the values from another WolfArray """
|
4073
|
+
|
3538
4074
|
fromarray: WolfArray
|
3539
4075
|
|
3540
4076
|
i1, j1 = self.get_ij_from_xy(fromarray.origx, fromarray.origy)
|
@@ -3560,8 +4096,14 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3560
4096
|
self.mask_data(self.nullvalue)
|
3561
4097
|
self.reset_plot()
|
3562
4098
|
|
3563
|
-
def set_values_sel(self, xy, z,update=True):
|
4099
|
+
def set_values_sel(self, xy:list[float], z:list[float], update:bool=True):
|
4100
|
+
"""
|
4101
|
+
Set values at the selected positions
|
3564
4102
|
|
4103
|
+
:param xy: [[x1,y1],[x2,y2],...]
|
4104
|
+
:param z: [z1,z2,...]
|
4105
|
+
:param update: update the plot
|
4106
|
+
"""
|
3565
4107
|
sel = np.asarray(xy)
|
3566
4108
|
|
3567
4109
|
if len(sel) == 1:
|
@@ -3574,8 +4116,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3574
4116
|
else:
|
3575
4117
|
ijall = np.asarray(self.get_ij_from_xy(sel[:, 0], sel[:, 1])).transpose()
|
3576
4118
|
|
3577
|
-
useful = np.where(
|
3578
|
-
(ijall[:, 0] >= 0) & (ijall[:, 0] < self.nbx) & (ijall[:, 1] >= 0) & (ijall[:, 1] < self.nby))
|
4119
|
+
useful = np.where((ijall[:, 0] >= 0) & (ijall[:, 0] < self.nbx) & (ijall[:, 1] >= 0) & (ijall[:, 1] < self.nby))
|
3579
4120
|
|
3580
4121
|
self.array[ijall[useful, 0], ijall[useful, 1]] = z[useful]
|
3581
4122
|
|
@@ -3585,6 +4126,10 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3585
4126
|
self.reset_plot()
|
3586
4127
|
|
3587
4128
|
def init_from_new(self, dlg: NewArray):
|
4129
|
+
"""
|
4130
|
+
Initialize the array properties from the NewArray dialog
|
4131
|
+
"""
|
4132
|
+
|
3588
4133
|
self.dx = float(dlg.dx.Value)
|
3589
4134
|
self.dy = float(dlg.dy.Value)
|
3590
4135
|
self.nbx = int(dlg.nbx.Value)
|
@@ -3595,7 +4140,16 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3595
4140
|
self.array = ma.MaskedArray(np.ones((self.nbx, self.nby), order='F', dtype=np.float32))
|
3596
4141
|
self.mask_reset()
|
3597
4142
|
|
3598
|
-
def init_from_header(self, myhead: header_wolf, dtype:np.dtype = None):
|
4143
|
+
def init_from_header(self, myhead: header_wolf, dtype:np.dtype = None, force_type_from_header:bool=False):
|
4144
|
+
"""
|
4145
|
+
Initialize the array properties from a header_wolf object
|
4146
|
+
|
4147
|
+
:param myhead: header_wolf object
|
4148
|
+
:param dtype: numpy dtype
|
4149
|
+
:param force_type_from_header: force the type from the header passed as argument
|
4150
|
+
"""
|
4151
|
+
if force_type_from_header:
|
4152
|
+
self.wolftype = myhead.wolftype
|
3599
4153
|
|
3600
4154
|
if dtype is None:
|
3601
4155
|
if self.wolftype == WOLF_ARRAY_FULL_DOUBLE:
|
@@ -3619,11 +4173,15 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3619
4173
|
self.array = ma.MaskedArray(np.ones((self.nbx, self.nby), order='F', dtype=dtype))
|
3620
4174
|
self.mask_reset()
|
3621
4175
|
|
3622
|
-
def interpolation2D(self):
|
4176
|
+
def interpolation2D(self, key:str='1'):
|
4177
|
+
""" Interpolation 2D basde on selected points in key 1 """
|
4178
|
+
|
4179
|
+
#FIXME : auhtorize interpolation on other keys
|
3623
4180
|
|
3624
|
-
|
4181
|
+
key = str(key)
|
4182
|
+
if key in self.mngselection.selections.keys():
|
3625
4183
|
if len(self.mngselection.myselection)>0:
|
3626
|
-
curlist = self.mngselection.selections[
|
4184
|
+
curlist = self.mngselection.selections[key]['select']
|
3627
4185
|
cursel = self.mngselection.myselection
|
3628
4186
|
if len(curlist) > 0:
|
3629
4187
|
ij = [self.get_ij_from_xy(cur[0], cur[1]) for cur in curlist]
|
@@ -3645,60 +4203,98 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3645
4203
|
|
3646
4204
|
self.reset_plot()
|
3647
4205
|
|
3648
|
-
def copy_mask(self, source:"WolfArray", forcenullvalue= False):
|
4206
|
+
def copy_mask(self, source:"WolfArray", forcenullvalue:bool= False, link:bool=True):
|
4207
|
+
"""
|
4208
|
+
Copy/Link the mask from another WolfArray
|
4209
|
+
|
4210
|
+
:param source: WolfArray source
|
4211
|
+
:param forcenullvalue: force nullvalue in the masked zone
|
4212
|
+
:param link: link the mask if True (default), copy it otherwise
|
4213
|
+
"""
|
4214
|
+
|
4215
|
+
assert self.shape == source.shape, _('Bad shape')
|
3649
4216
|
|
3650
4217
|
if forcenullvalue:
|
3651
4218
|
self.array[np.where(source.array.mask)] = self.nullvalue
|
3652
4219
|
|
3653
|
-
|
4220
|
+
if link:
|
4221
|
+
self.array.mask = source.array.mask
|
4222
|
+
else:
|
4223
|
+
self.array.mask = source.array.mask.copy()
|
4224
|
+
|
3654
4225
|
self.nbnotnull = source.nbnotnull
|
3655
4226
|
|
3656
|
-
|
3657
|
-
self.reset_plot()
|
4227
|
+
self.reset_plot()
|
3658
4228
|
|
3659
|
-
def
|
3660
|
-
|
4229
|
+
def mask_union(self, source:"WolfArray", link:bool=True):
|
4230
|
+
"""
|
4231
|
+
Union of the mask with another WolfArray
|
3661
4232
|
|
3662
|
-
|
4233
|
+
:param source: WolfArray source
|
4234
|
+
:param link: link the mask if True (default), copy it otherwise
|
4235
|
+
"""
|
3663
4236
|
|
3664
4237
|
union = self.array.mask & source.array.mask
|
3665
4238
|
|
3666
|
-
self.array[(~union) & (self.array.mask)] =
|
3667
|
-
source.array[(~union) & (source.array.mask)] =
|
4239
|
+
self.array[(~union) & (self.array.mask)] = self.nullvalue
|
4240
|
+
source.array[(~union) & (source.array.mask)] = self.nullvalue
|
3668
4241
|
|
3669
|
-
self.array.mask = union
|
3670
|
-
source.array.mask = union
|
3671
4242
|
|
3672
|
-
|
4243
|
+
if link:
|
4244
|
+
self.array.mask = union
|
4245
|
+
source.array.mask = union
|
4246
|
+
else:
|
4247
|
+
self.array.mask = union.copy()
|
4248
|
+
source.array.mask = union.copy()
|
3673
4249
|
|
3674
|
-
|
3675
|
-
|
4250
|
+
self.reset_plot()
|
4251
|
+
source.reset_plot()
|
3676
4252
|
|
3677
|
-
def copy_mask_log(self,mask):
|
3678
|
-
|
3679
|
-
|
4253
|
+
def copy_mask_log(self, mask:np.ndarray, link:bool=True):
|
4254
|
+
"""
|
4255
|
+
Copy the mask from a numpy array
|
3680
4256
|
|
3681
|
-
|
3682
|
-
|
4257
|
+
:param mask: numpy array
|
4258
|
+
:param link: link the mask if True (default), copy it otherwise
|
4259
|
+
"""
|
4260
|
+
assert self.shape == mask.shape, _('Bad shape')
|
4261
|
+
|
4262
|
+
if link:
|
4263
|
+
self.array.mask = mask
|
4264
|
+
else:
|
4265
|
+
self.array.mask = mask.copy()
|
4266
|
+
|
4267
|
+
self.reset_plot()
|
3683
4268
|
|
3684
4269
|
def check_plot(self):
|
4270
|
+
""" Make sure the array is plotted """
|
4271
|
+
|
3685
4272
|
self.plotted = True
|
3686
4273
|
|
3687
4274
|
if not self.loaded and self.filename != '':
|
4275
|
+
# if not loaded, load it
|
3688
4276
|
self.read_data()
|
3689
4277
|
if self.masknull:
|
3690
|
-
self.mask_data(
|
4278
|
+
self.mask_data(self.nullvalue)
|
3691
4279
|
|
3692
4280
|
self.loaded = True
|
3693
4281
|
|
3694
4282
|
if self.rgb is None:
|
3695
4283
|
self.updatepalette(0)
|
3696
4284
|
|
3697
|
-
def uncheck_plot(self, unload=True, forceresetOGL=False, askquestion=True):
|
4285
|
+
def uncheck_plot(self, unload:bool=True, forceresetOGL:bool=False, askquestion:bool=True):
|
4286
|
+
"""
|
4287
|
+
Make sure the array is not plotted
|
4288
|
+
|
4289
|
+
:param unload: unload the data if True (default), keep it otherwise
|
4290
|
+
:param forceresetOGL: force the reset of the OpenGL lists
|
4291
|
+
:param askquestion: ask the question if True and a wx App is running (default), don't ask it otherwise
|
4292
|
+
"""
|
4293
|
+
|
3698
4294
|
self.plotted = False
|
3699
4295
|
|
3700
4296
|
if unload and self.filename != '':
|
3701
|
-
if askquestion:
|
4297
|
+
if askquestion and self.wx_exists:
|
3702
4298
|
dlg = wx.MessageDialog(None,
|
3703
4299
|
_('Do you want to unload data? \n If YES, the data will be reloaded from file once checekd \n If not saved, modifications will be lost !!'),
|
3704
4300
|
style=wx.YES_NO)
|
@@ -3714,7 +4310,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3714
4310
|
return
|
3715
4311
|
|
3716
4312
|
if not forceresetOGL:
|
3717
|
-
if askquestion:
|
4313
|
+
if askquestion and self.wx_exists:
|
3718
4314
|
dlg = wx.MessageDialog(None, _('Do you want to reset OpenGL lists?'), style=wx.YES_NO)
|
3719
4315
|
ret = dlg.ShowModal()
|
3720
4316
|
if ret == wx.ID_YES:
|
@@ -3724,7 +4320,13 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3724
4320
|
self.delete_lists()
|
3725
4321
|
self.rgb = None
|
3726
4322
|
|
3727
|
-
def get_header(self, abs=True) -> header_wolf:
|
4323
|
+
def get_header(self, abs:bool=True) -> header_wolf:
|
4324
|
+
"""
|
4325
|
+
Return a header_wolf object - different from the self object header
|
4326
|
+
|
4327
|
+
:param abs: if True (default), return an absolute header (shifted origin) and translation set to 0.
|
4328
|
+
"""
|
4329
|
+
|
3728
4330
|
curhead = header_wolf()
|
3729
4331
|
|
3730
4332
|
curhead.origx = self.origx
|
@@ -3745,7 +4347,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3745
4347
|
|
3746
4348
|
curhead.head_blocks = self.head_blocks.copy()
|
3747
4349
|
|
3748
|
-
curhead.
|
4350
|
+
curhead.wolftype = self.wolftype
|
3749
4351
|
|
3750
4352
|
if abs:
|
3751
4353
|
curhead.origx += curhead.translx
|
@@ -3758,6 +4360,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3758
4360
|
return curhead
|
3759
4361
|
|
3760
4362
|
def set_header(self, header: header_wolf):
|
4363
|
+
""" Set the header from a header_wolf object """
|
3761
4364
|
self.origx = header.origx
|
3762
4365
|
self.origy = header.origy
|
3763
4366
|
self.origz = header.origz
|
@@ -3774,8 +4377,6 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3774
4377
|
self.nby = header.nby
|
3775
4378
|
self.nbz = header.nbz
|
3776
4379
|
|
3777
|
-
self.nbdims = header.nbdims
|
3778
|
-
|
3779
4380
|
self.head_blocks = header.head_blocks.copy()
|
3780
4381
|
|
3781
4382
|
self.add_ops_sel()
|
@@ -3783,7 +4384,6 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3783
4384
|
def __add__(self, other):
|
3784
4385
|
"""Surcharge de l'opérateur d'addition"""
|
3785
4386
|
newArray = WolfArray()
|
3786
|
-
newArray.nbdims = self.nbdims
|
3787
4387
|
newArray.nbx = self.nbx
|
3788
4388
|
newArray.nby = self.nby
|
3789
4389
|
newArray.dx = self.dx
|
@@ -3809,7 +4409,6 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3809
4409
|
def __mul__(self, other):
|
3810
4410
|
"""Surcharge de l'opérateur d'addition"""
|
3811
4411
|
newArray = WolfArray()
|
3812
|
-
newArray.nbdims = self.nbdims
|
3813
4412
|
newArray.nbx = self.nbx
|
3814
4413
|
newArray.nby = self.nby
|
3815
4414
|
newArray.dx = self.dx
|
@@ -3835,7 +4434,6 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3835
4434
|
def __sub__(self, other):
|
3836
4435
|
"""Surcharge de l'opérateur de soustraction"""
|
3837
4436
|
newArray = WolfArray()
|
3838
|
-
newArray.nbdims = self.nbdims
|
3839
4437
|
newArray.nbx = self.nbx
|
3840
4438
|
newArray.nby = self.nby
|
3841
4439
|
newArray.dx = self.dx
|
@@ -3861,7 +4459,6 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3861
4459
|
def __pow__(self, other):
|
3862
4460
|
"""Surcharge de l'opérateur puissance"""
|
3863
4461
|
newArray = WolfArray()
|
3864
|
-
newArray.nbdims = self.nbdims
|
3865
4462
|
newArray.nbx = self.nbx
|
3866
4463
|
newArray.nby = self.nby
|
3867
4464
|
newArray.dx = self.dx
|
@@ -3883,7 +4480,6 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3883
4480
|
def __truediv__(self, other):
|
3884
4481
|
"""Surcharge de l'opérateur division"""
|
3885
4482
|
newArray = WolfArray()
|
3886
|
-
newArray.nbdims = self.nbdims
|
3887
4483
|
newArray.nbx = self.nbx
|
3888
4484
|
newArray.nby = self.nby
|
3889
4485
|
newArray.dx = self.dx
|
@@ -3908,6 +4504,11 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3908
4504
|
return newArray
|
3909
4505
|
|
3910
4506
|
def mask_outsidepoly(self, myvect: vector):
|
4507
|
+
"""
|
4508
|
+
Mask nodes outside a polygon and set values to nullvalue
|
4509
|
+
|
4510
|
+
:param myvect: target vector in global coordinates
|
4511
|
+
"""
|
3911
4512
|
# The polygon here is in world coordinates
|
3912
4513
|
# (coord will be converted back with translation, origin and dx/dy)
|
3913
4514
|
# (mesh coord, 0-based)
|
@@ -3916,7 +4517,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3916
4517
|
mask[:,:] = True # Mask everything
|
3917
4518
|
|
3918
4519
|
# trouve les indices dans le polygone
|
3919
|
-
myij = self.get_ij_inside_polygon(myvect,False)
|
4520
|
+
myij = self.get_ij_inside_polygon(myvect, False)
|
3920
4521
|
# démasquage des mailles contenues
|
3921
4522
|
mask[myij[:,0],myij[:,1]] = False
|
3922
4523
|
# annulation des valeurs en dehors du polygone
|
@@ -3932,31 +4533,18 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3932
4533
|
# FIXME This operation seems to contradict mask[:,:] = True
|
3933
4534
|
self.mask_data(self.nullvalue)
|
3934
4535
|
|
3935
|
-
def get_xy_infootprint_vect(self, myvect: vector) -> np.ndarray:
|
3936
|
-
|
3937
|
-
myptsij = self.get_ij_infootprint_vect(myvect)
|
3938
|
-
mypts=np.asarray(myptsij.copy(),dtype=np.float64)
|
3939
|
-
mypts[:,0] = (mypts[:,0]+.5)*self.dx +self.origx +self.translx
|
3940
|
-
mypts[:,1] = (mypts[:,1]+.5)*self.dy +self.origy +self.transly
|
3941
|
-
|
3942
|
-
return mypts,myptsij
|
3943
4536
|
|
3944
|
-
|
3945
|
-
|
3946
|
-
|
3947
|
-
|
3948
|
-
|
3949
|
-
|
3950
|
-
j2 = min(j2,self.nby-1)
|
3951
|
-
xv,yv = np.meshgrid(np.arange(i1,i2+1),np.arange(j1,j2+1))
|
3952
|
-
mypts = np.hstack((xv.flatten()[:,np.newaxis],yv.flatten()[:,np.newaxis]))
|
3953
|
-
|
3954
|
-
return mypts
|
3955
|
-
|
3956
|
-
def get_xy_inside_polygon(self, myvect: vector, usemask=True):
|
4537
|
+
# *************************************************************************************************************************
|
4538
|
+
# POSITION and VALUES associated to a vector/polygon/polyline
|
4539
|
+
# These functions can not be stored in header_wolf, because wa can use the mask of the array to limit the search
|
4540
|
+
# These functions are also present in WolfResults_2D, but they are not exactly the same dur to the structure of the results
|
4541
|
+
# *************************************************************************************************************************
|
4542
|
+
def get_xy_inside_polygon(self, myvect: vector, usemask:bool=True):
|
3957
4543
|
"""
|
3958
|
-
|
3959
|
-
|
4544
|
+
Return the coordinates inside a polygon
|
4545
|
+
|
4546
|
+
:param myvect = target vector
|
4547
|
+
:param usemask = limit potential nodes to unmaksed nodes
|
3960
4548
|
"""
|
3961
4549
|
|
3962
4550
|
myvect.find_minmax()
|
@@ -3974,10 +4562,12 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3974
4562
|
|
3975
4563
|
return mypointsxy
|
3976
4564
|
|
3977
|
-
def get_xy_under_polyline(self, myvect: vector, usemask=True):
|
4565
|
+
def get_xy_under_polyline(self, myvect: vector, usemask:bool=True):
|
3978
4566
|
"""
|
3979
|
-
|
3980
|
-
|
4567
|
+
Return the coordinates along a polyline
|
4568
|
+
|
4569
|
+
:param myvect = target vector
|
4570
|
+
:param usemask = limit potential nodes to unmaksed nodes
|
3981
4571
|
"""
|
3982
4572
|
|
3983
4573
|
allij = self.get_ij_under_polyline(myvect, usemask)
|
@@ -3985,18 +4575,12 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
3985
4575
|
|
3986
4576
|
return mypoints
|
3987
4577
|
|
3988
|
-
def
|
3989
|
-
return np.asarray((xy[:,0]-self.origx -self.translx)/self.dx-.5,dtype=np.int32), \
|
3990
|
-
np.asarray((xy[:,1]-self.origy -self.transly)/self.dy-.5,dtype=np.int32)
|
3991
|
-
|
3992
|
-
def convert_ij2xy(self,xy):
|
3993
|
-
return np.asarray((xy[:,0]+.5)*self.dx+self.origx +self.translx ,dtype=np.float64), \
|
3994
|
-
np.asarray((xy[:,1]+.5)*self.dy+self.origy +self.transly ,dtype=np.float64)
|
3995
|
-
|
3996
|
-
def get_ij_inside_polygon(self, myvect: vector, usemask=True):
|
4578
|
+
def get_ij_inside_polygon(self, myvect: vector, usemask:bool=True):
|
3997
4579
|
"""
|
3998
|
-
|
3999
|
-
|
4580
|
+
Return the indices inside a polygon
|
4581
|
+
|
4582
|
+
:param myvect = target vector
|
4583
|
+
:param usemask = limit potential nodes to unmaksed nodes
|
4000
4584
|
"""
|
4001
4585
|
|
4002
4586
|
myvect.find_minmax()
|
@@ -4014,10 +4598,12 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4014
4598
|
|
4015
4599
|
return mypointsij
|
4016
4600
|
|
4017
|
-
def get_ij_under_polyline(self, myvect: vector, usemask=True):
|
4601
|
+
def get_ij_under_polyline(self, myvect: vector, usemask:bool=True):
|
4018
4602
|
"""
|
4019
|
-
|
4020
|
-
|
4603
|
+
Return the indices along a polyline
|
4604
|
+
|
4605
|
+
:param myvect = target vector
|
4606
|
+
:param usedmask = limit potential nodes to unmaksed nodes
|
4021
4607
|
"""
|
4022
4608
|
|
4023
4609
|
ds = min(self.dx, self.dy)
|
@@ -4033,7 +4619,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4033
4619
|
|
4034
4620
|
return allij
|
4035
4621
|
|
4036
|
-
def get_values_insidepoly(self, myvect: vector, usemask=True, getxy=False):
|
4622
|
+
def get_values_insidepoly(self, myvect: vector, usemask:bool=True, getxy:bool=False):
|
4037
4623
|
"""
|
4038
4624
|
Récupération des valeurs contenues dans un polygone
|
4039
4625
|
|
@@ -4048,7 +4634,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4048
4634
|
else:
|
4049
4635
|
return myvalues, None
|
4050
4636
|
|
4051
|
-
def get_values_underpoly(self, myvect: vector, usemask=True, getxy=False):
|
4637
|
+
def get_values_underpoly(self, myvect: vector, usemask:bool=True, getxy:bool=False):
|
4052
4638
|
"""
|
4053
4639
|
Récupération des valeurs contenues sous une polyligne
|
4054
4640
|
|
@@ -4064,7 +4650,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4064
4650
|
else:
|
4065
4651
|
return myvalues, None
|
4066
4652
|
|
4067
|
-
def get_all_values_insidepoly(self, myvect: vector, usemask=True, getxy=False):
|
4653
|
+
def get_all_values_insidepoly(self, myvect: vector, usemask:bool=True, getxy:bool=False):
|
4068
4654
|
"""
|
4069
4655
|
Récupération de toutes les valeurs contenues dans un polygone
|
4070
4656
|
|
@@ -4077,7 +4663,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4077
4663
|
|
4078
4664
|
return self.get_values_insidepoly(myvect, usemask,getxy)
|
4079
4665
|
|
4080
|
-
def get_all_values_underpoly(self, myvect: vector, usemask=True, getxy=False):
|
4666
|
+
def get_all_values_underpoly(self, myvect: vector, usemask:bool=True, getxy:bool=False):
|
4081
4667
|
"""
|
4082
4668
|
Récupération de toutes les valeurs sous la polyligne
|
4083
4669
|
|
@@ -4090,22 +4676,29 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4090
4676
|
|
4091
4677
|
return self.get_values_underpoly(myvect, usemask, getxy)
|
4092
4678
|
|
4679
|
+
# *************************************************************************************************************************
|
4680
|
+
# END POSITION and VALUES associated to a vector/polygon/polyline
|
4681
|
+
# *************************************************************************************************************************
|
4682
|
+
|
4093
4683
|
def reset(self):
|
4094
|
-
|
4684
|
+
""" Reset the array to nullvalue """
|
4685
|
+
|
4095
4686
|
if self.nbdims == 2:
|
4096
|
-
self.array[:, :] =
|
4687
|
+
self.array[:, :] = self.nullvalue
|
4097
4688
|
elif self.nbdims == 3:
|
4098
|
-
self.array[:, :, :] =
|
4689
|
+
self.array[:, :, :] = self.nullvalue
|
4099
4690
|
|
4100
4691
|
def allocate_ressources(self):
|
4101
4692
|
""" Memory Allocation according to dtype/wolftype"""
|
4693
|
+
|
4102
4694
|
if self.nbdims == 2:
|
4103
|
-
self.array = ma.ones([self.nbx, self.nby], dtype=self.dtype)
|
4695
|
+
self.array = ma.ones([self.nbx, self.nby], order='F', dtype=self.dtype)
|
4104
4696
|
elif self.nbdims == 3:
|
4105
|
-
self.array = ma.ones([self.nbx, self.nby, self.nbz], dtype=self.dtype)
|
4697
|
+
self.array = ma.ones([self.nbx, self.nby, self.nbz], order='F', dtype=self.dtype)
|
4106
4698
|
|
4107
4699
|
def read_all(self, which_band = None):
|
4108
4700
|
""" Lecture d'un Wolf aray depuis le nom de fichier """
|
4701
|
+
|
4109
4702
|
if not os.path.exists(self.filename):
|
4110
4703
|
if self.wx_exists:
|
4111
4704
|
logging.warning(_('No data file : ')+self.filename)
|
@@ -4162,8 +4755,15 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4162
4755
|
self.loaded = True
|
4163
4756
|
return
|
4164
4757
|
|
4165
|
-
def write_all(self, newpath = None):
|
4166
|
-
"""
|
4758
|
+
def write_all(self, newpath:str = None):
|
4759
|
+
"""
|
4760
|
+
Ecriture de tous les fichiers d'un Wolf array
|
4761
|
+
|
4762
|
+
:param newpath: path and filename with extension
|
4763
|
+
"""
|
4764
|
+
|
4765
|
+
if isinstance(newpath, Path):
|
4766
|
+
newpath = str(newpath)
|
4167
4767
|
|
4168
4768
|
if newpath is not None:
|
4169
4769
|
self.filename = newpath
|
@@ -4227,7 +4827,6 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4227
4827
|
|
4228
4828
|
super().read_txt_header(self.filename)
|
4229
4829
|
|
4230
|
-
|
4231
4830
|
def write_txt_header(self):
|
4232
4831
|
"""
|
4233
4832
|
Write header to txt file
|
@@ -4321,6 +4920,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4321
4920
|
self.loaded = True
|
4322
4921
|
|
4323
4922
|
def _read_binary_data(self, f, seek=0):
|
4923
|
+
""" Read binary data from file """
|
4324
4924
|
|
4325
4925
|
if seek > 0:
|
4326
4926
|
f.seek(0)
|
@@ -4353,13 +4953,15 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4353
4953
|
""" Ecriture du tableau en binaire """
|
4354
4954
|
self.array.data.transpose().tofile(self.filename, "")
|
4355
4955
|
|
4356
|
-
def write_xyz(self, fname):
|
4956
|
+
def write_xyz(self, fname:str):
|
4357
4957
|
""" Ecriture d un fichier xyz avec toutes les données du Wolf Array """
|
4358
4958
|
my_file = XYZFile(fname)
|
4359
4959
|
my_file.fill_from_wolf_array(self)
|
4360
4960
|
my_file.write_to_file()
|
4361
4961
|
|
4362
|
-
def get_xyz(self, which='all'):
|
4962
|
+
def get_xyz(self, which='all') -> np.ndarray:
|
4963
|
+
""" Return an array of xyz coordinates and values """
|
4964
|
+
|
4363
4965
|
x1, y1 = self.get_xy_from_ij(0, 0)
|
4364
4966
|
x2, y2 = self.get_xy_from_ij(self.nbx, self.nby, aswolf=True)
|
4365
4967
|
xloc = np.linspace(x1, x2, self.nbx)
|
@@ -4372,25 +4974,45 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4372
4974
|
|
4373
4975
|
return xyz[filter]
|
4374
4976
|
|
4375
|
-
def set_general_frame_from_xyz(self, fname, dx, dy):
|
4376
|
-
"""
|
4977
|
+
def set_general_frame_from_xyz(self, fname:str, dx:float, dy:float, border_size:int=5):
|
4978
|
+
"""
|
4979
|
+
Lecture d'un fichier texte xyz et initialisation des données de base
|
4980
|
+
|
4981
|
+
:param fname: nom du fichier xyz
|
4982
|
+
:param dx: pas en x
|
4983
|
+
:param dy: pas en y
|
4984
|
+
:param border_size: nombre de mailles de bordure en plus de l'extension spatiale du fichier
|
4985
|
+
"""
|
4986
|
+
|
4377
4987
|
my_file = XYZFile(fname)
|
4378
4988
|
my_file.read_from_file()
|
4379
4989
|
(xlim, ylim) = my_file.get_extent()
|
4380
4990
|
|
4381
4991
|
self.dx = dx
|
4382
4992
|
self.dy = dy
|
4383
|
-
self.origx = m.floor(xlim[0]) -
|
4384
|
-
self.origy = m.floor(ylim[0]) -
|
4385
|
-
self.nbx = int((m.floor(xlim[1]) - m.ceil(xlim[0])) / self.dx) +
|
4386
|
-
self.nby = int((m.floor(ylim[1]) - m.ceil(ylim[0])) / self.dy) +
|
4993
|
+
self.origx = m.floor(xlim[0]) - float(border_size) * self.dx
|
4994
|
+
self.origy = m.floor(ylim[0]) - float(border_size) * self.dy
|
4995
|
+
self.nbx = int((m.floor(xlim[1]) - m.ceil(xlim[0])) / self.dx) + 2*border_size
|
4996
|
+
self.nby = int((m.floor(ylim[1]) - m.ceil(ylim[0])) / self.dy) + 2*border_size
|
4387
4997
|
|
4388
4998
|
self.array = np.ma.zeros((self.nbx, self.nby))
|
4389
4999
|
return my_file
|
4390
5000
|
|
4391
|
-
def fillin_from_xyz(self, xyz):
|
4392
|
-
|
4393
|
-
|
5001
|
+
def fillin_from_xyz(self, xyz:np.ndarray):
|
5002
|
+
""" Remplissage du tableau à partir d'un tableau xyz """
|
5003
|
+
|
5004
|
+
if self.dtype == np.float32:
|
5005
|
+
self.array.data[self.get_ij_from_xy(xyz[:, 0], xyz[:, 1])] = np.float32(xyz[:, 2])
|
5006
|
+
elif self.dtype == np.float64:
|
5007
|
+
self.array.data[self.get_ij_from_xy(xyz[:, 0], xyz[:, 1])] = np.float64(xyz[:, 2])
|
5008
|
+
elif self.dtype == np.int32:
|
5009
|
+
self.array.data[self.get_ij_from_xy(xyz[:, 0], xyz[:, 1])] = np.int32(xyz[:, 2])
|
5010
|
+
elif self.dtype == np.int16:
|
5011
|
+
self.array.data[self.get_ij_from_xy(xyz[:, 0], xyz[:, 1])] = np.int16(xyz[:, 2])
|
5012
|
+
elif self.dtype == np.int8:
|
5013
|
+
self.array.data[self.get_ij_from_xy(xyz[:, 0], xyz[:, 1])] = np.int8(xyz[:, 2])
|
5014
|
+
else:
|
5015
|
+
logging.warning(_('Type not supported : ')+str(self.dtype))
|
4394
5016
|
|
4395
5017
|
def mask_force_null(self):
|
4396
5018
|
"""
|
@@ -4398,8 +5020,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4398
5020
|
"""
|
4399
5021
|
self.mask_reset()
|
4400
5022
|
self.mask_data(self.nullvalue)
|
4401
|
-
|
4402
|
-
self.reset_plot()
|
5023
|
+
self.reset_plot()
|
4403
5024
|
|
4404
5025
|
def unmask(self):
|
4405
5026
|
""" alias to mask_reset """
|
@@ -4413,7 +5034,6 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4413
5034
|
"""
|
4414
5035
|
Unmask everything
|
4415
5036
|
"""
|
4416
|
-
# FIXME For WolfArray_Sim2D, this is strange since that class is there to share a mask...
|
4417
5037
|
|
4418
5038
|
if self.nbdims == 2:
|
4419
5039
|
# FIXME if WolfArray_Sim2D mask linking should work
|
@@ -4421,19 +5041,29 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4421
5041
|
# to avoid replacing the linked mask by a (non linked) one.
|
4422
5042
|
|
4423
5043
|
if isinstance(self.array.mask, np.bool_):
|
5044
|
+
# mask is not an array, but a single boolean value
|
4424
5045
|
self.array.mask = np.zeros(self.array.shape)
|
4425
5046
|
else:
|
4426
5047
|
self.array.mask.fill(False) # False == not masked
|
5048
|
+
|
4427
5049
|
self.nbnotnull = self.nbx * self.nby
|
5050
|
+
|
4428
5051
|
elif self.nbdims == 3:
|
4429
|
-
self.array.mask
|
5052
|
+
if isinstance(self.array.mask, np.bool_):
|
5053
|
+
self.array.mask = np.zeros((self.nbx, self.nby, self.nbz))
|
5054
|
+
else:
|
5055
|
+
self.array.mask.fill(False) # False == not masked
|
5056
|
+
|
4430
5057
|
self.nbnotnull = self.nbx * self.nby * self.nbz
|
4431
5058
|
|
4432
5059
|
def count(self):
|
5060
|
+
""" Count the number of not masked values """
|
5061
|
+
|
4433
5062
|
self.nbnotnull = self.array.count()
|
4434
5063
|
return self.nbnotnull
|
4435
5064
|
|
4436
5065
|
def mask_data(self, value):
|
5066
|
+
""" Mask cell where values are equal to `value`"""
|
4437
5067
|
if self.array is None:
|
4438
5068
|
return
|
4439
5069
|
|
@@ -4441,10 +5071,22 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4441
5071
|
value=int(value)
|
4442
5072
|
|
4443
5073
|
if value is not None:
|
4444
|
-
|
4445
|
-
|
5074
|
+
|
5075
|
+
if isinstance(self.array.mask, np.bool_):
|
5076
|
+
# mask is not an array, but a single boolean value
|
5077
|
+
# we must create a new mask array
|
5078
|
+
if np.isnan(value) or math.isnan(value):
|
5079
|
+
self.array.mask = np.isnan(self.array.data)
|
5080
|
+
else:
|
5081
|
+
self.array.mask = self.array.data == value
|
4446
5082
|
else:
|
4447
|
-
|
5083
|
+
# Copy to prevent unlinking the mask (see `mask_reset`)
|
5084
|
+
if np.isnan(value) or math.isnan(value):
|
5085
|
+
np.copyto(self.array.mask, np.isnan(self.array.data))
|
5086
|
+
# self.array.mask[:,:] = np.isnan(self.array.data)
|
5087
|
+
else:
|
5088
|
+
np.copyto(self.array.mask, self.array.data == value)
|
5089
|
+
# self.array.mask[:,:] = self.array.data == value
|
4448
5090
|
self.count()
|
4449
5091
|
|
4450
5092
|
def mask_lower(self, value):
|
@@ -4457,6 +5099,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4457
5099
|
self.count()
|
4458
5100
|
|
4459
5101
|
def mask_lowerequal(self, value):
|
5102
|
+
""" Mask cell where values are lower or equal than `value`"""
|
4460
5103
|
if self.array is None:
|
4461
5104
|
return
|
4462
5105
|
|
@@ -4465,22 +5108,30 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4465
5108
|
self.count()
|
4466
5109
|
|
4467
5110
|
def set_nullvalue_in_mask(self):
|
5111
|
+
""" Set nullvalue in masked cells """
|
4468
5112
|
if self.array is None:
|
4469
5113
|
return
|
4470
5114
|
self.array.data[self.array.mask] = self.nullvalue
|
4471
5115
|
|
4472
5116
|
def reset_plot(self, whichpal=0, mimic=True):
|
4473
|
-
|
4474
|
-
|
4475
|
-
if mimic:
|
4476
|
-
for cur in self.linkedarrays:
|
4477
|
-
if id(cur.mypal) == id(self.mypal) and id(self) !=id(cur):
|
4478
|
-
cur.reset_plot(whichpal=whichpal, mimic=False)
|
5117
|
+
""" Reset plot of the array """
|
4479
5118
|
|
4480
5119
|
self.count()
|
4481
|
-
self.
|
5120
|
+
if self.plotted:
|
5121
|
+
self.delete_lists()
|
5122
|
+
|
5123
|
+
if mimic:
|
5124
|
+
for cur in self.linkedarrays:
|
5125
|
+
if id(cur.mypal) == id(self.mypal) and id(self) !=id(cur):
|
5126
|
+
cur.reset_plot(whichpal=whichpal, mimic=False)
|
5127
|
+
|
5128
|
+
self.updatepalette(whichpal)
|
5129
|
+
|
5130
|
+
if self.mapviewer is not None:
|
5131
|
+
self.mapviewer.Refresh()
|
4482
5132
|
|
4483
5133
|
def mask_allexceptdata(self, value):
|
5134
|
+
""" Mask cell where values are different from `value`"""
|
4484
5135
|
if self.array is None:
|
4485
5136
|
return
|
4486
5137
|
|
@@ -4489,13 +5140,20 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4489
5140
|
self.count()
|
4490
5141
|
|
4491
5142
|
def mask_invert(self):
|
5143
|
+
""" Invert the mask """
|
4492
5144
|
if self.array is None:
|
4493
5145
|
return
|
4494
5146
|
# Copy to prevent unlinking the mask (see `mask_reset`)
|
4495
5147
|
np.copyto(self.array.mask, np.logical_not(self.array.mask))
|
4496
5148
|
self.count()
|
4497
5149
|
|
4498
|
-
def meshgrid(self, mode='gc'):
|
5150
|
+
def meshgrid(self, mode:Literal['gc', 'borders']='gc'):
|
5151
|
+
"""
|
5152
|
+
Création d'un maillage 2D
|
5153
|
+
|
5154
|
+
:param mode: 'gc' pour les centres de mailles, 'borders' pour les bords de mailles
|
5155
|
+
"""
|
5156
|
+
|
4499
5157
|
x_start = self.translx + self.origx
|
4500
5158
|
y_start = self.transly + self.origy
|
4501
5159
|
if mode == 'gc':
|
@@ -4508,22 +5166,41 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4508
5166
|
y, x = np.meshgrid(y_discr, x_discr)
|
4509
5167
|
return x, y
|
4510
5168
|
|
4511
|
-
def crop(self, i_start, j_start, nbx, nby, k_start=1, nbz=1):
|
4512
|
-
|
5169
|
+
def crop(self, i_start:int, j_start:int, nbx:int, nby:int, k_start:int=1, nbz:int=1):
|
5170
|
+
"""
|
5171
|
+
Crop the array
|
5172
|
+
|
5173
|
+
:param i_start: start index in x
|
5174
|
+
:param j_start: start index in y
|
5175
|
+
:param nbx: number of cells in x
|
5176
|
+
:param nby: number of cells in y
|
5177
|
+
:param k_start: start index in z
|
5178
|
+
:param nbz: number of cells in z
|
5179
|
+
|
5180
|
+
:return: cropped array, WolfArray instance
|
5181
|
+
"""
|
5182
|
+
|
5183
|
+
assert type(i_start) == int, "i_start must be an integer"
|
5184
|
+
assert type(j_start) == int, "j_start must be an integer"
|
5185
|
+
assert type(nbx) == int, "nbx must be an integer"
|
5186
|
+
assert type(nby) == int, "nby must be an integer"
|
5187
|
+
assert type(k_start) == int, "k_start must be an integer"
|
5188
|
+
assert type(nbz) == int, "nbz must be an integer"
|
5189
|
+
|
4513
5190
|
newWolfArray = WolfArray()
|
4514
5191
|
newWolfArray.nbx = nbx
|
4515
5192
|
newWolfArray.nby = nby
|
4516
5193
|
newWolfArray.dx = self.dx
|
4517
5194
|
newWolfArray.dy = self.dy
|
4518
|
-
newWolfArray.origx = self.origx + i_start * self.dx
|
4519
|
-
newWolfArray.origy = self.origy + j_start * self.dy
|
5195
|
+
newWolfArray.origx = self.origx + float(i_start) * self.dx
|
5196
|
+
newWolfArray.origy = self.origy + float(j_start) * self.dy
|
4520
5197
|
newWolfArray.translx = self.translx
|
4521
5198
|
newWolfArray.transly = self.transly
|
4522
5199
|
|
4523
5200
|
if self.nbdims == 3:
|
4524
5201
|
newWolfArray.nbz = nbz
|
4525
5202
|
newWolfArray.dz = self.dz
|
4526
|
-
newWolfArray.origz = self.origz + k_start * self.dz
|
5203
|
+
newWolfArray.origz = self.origz + float(k_start) * self.dz
|
4527
5204
|
newWolfArray.translz = self.translz
|
4528
5205
|
|
4529
5206
|
newWolfArray.array = self.array[i_start:i_start + nbx, j_start:j_start + nby, k_start:k_start + nbz]
|
@@ -4532,64 +5209,32 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4532
5209
|
|
4533
5210
|
return newWolfArray
|
4534
5211
|
|
4535
|
-
def extremum(self, which='min'):
|
5212
|
+
def extremum(self, which:Literal['min','max']='min'):
|
5213
|
+
""" Return the extremum value """
|
5214
|
+
|
4536
5215
|
if which == 'min':
|
4537
5216
|
my_extr = np.amin(self.array)
|
4538
|
-
|
5217
|
+
elif which == 'max':
|
4539
5218
|
my_extr = np.amax(self.array)
|
4540
|
-
|
4541
|
-
return my_extr
|
4542
|
-
|
4543
|
-
def get_bounds(self, abs=True):
|
4544
|
-
if abs:
|
4545
|
-
return ([self.origx + self.translx, self.origx + self.translx + float(self.nbx) * self.dx],
|
4546
|
-
[self.origy + self.transly, self.origy + self.transly + float(self.nby) * self.dy])
|
4547
5219
|
else:
|
4548
|
-
|
4549
|
-
|
4550
|
-
|
4551
|
-
def find_intersection(self, other, ij=False):
|
4552
|
-
|
4553
|
-
mybounds = self.get_bounds()
|
4554
|
-
otherbounds = other.get_bounds()
|
4555
|
-
|
4556
|
-
if otherbounds[0][0] > mybounds[0][1]:
|
4557
|
-
return None
|
4558
|
-
elif otherbounds[1][0] > mybounds[1][1]:
|
4559
|
-
return None
|
4560
|
-
elif otherbounds[0][1] < mybounds[0][0]:
|
4561
|
-
return None
|
4562
|
-
elif otherbounds[1][1] < mybounds[0][1]:
|
4563
|
-
return None
|
4564
|
-
else:
|
4565
|
-
ox = max(mybounds[0][0], otherbounds[0][0])
|
4566
|
-
oy = max(mybounds[1][0], otherbounds[1][0])
|
4567
|
-
ex = min(mybounds[0][1], otherbounds[0][1])
|
4568
|
-
ey = min(mybounds[1][1], otherbounds[1][1])
|
4569
|
-
if ij:
|
4570
|
-
i1, j1 = self.get_ij_from_xy(ox, oy)
|
4571
|
-
i2, j2 = self.get_ij_from_xy(ex, ey)
|
5220
|
+
logging.warning(_('Extremum not supported : ')+which)
|
5221
|
+
my_extr = -99999.
|
4572
5222
|
|
4573
|
-
|
4574
|
-
i4, j4 = other.get_ij_from_xy(ex, ey)
|
4575
|
-
return ([[i1, i2], [j1, j2]],
|
4576
|
-
[[i3, i4], [j3, j4]])
|
4577
|
-
else:
|
4578
|
-
return ([ox, ex], [oy, ey])
|
4579
|
-
|
4580
|
-
def find_union(self, other):
|
4581
|
-
|
4582
|
-
mybounds = self.get_bounds()
|
4583
|
-
otherbounds = other.get_bounds()
|
5223
|
+
return my_extr
|
4584
5224
|
|
4585
|
-
|
4586
|
-
|
4587
|
-
|
4588
|
-
ey = max(mybounds[1][1], otherbounds[1][1])
|
5225
|
+
def get_value(self, x:float, y:float, z:float=0., nullvalue:float=-99999):
|
5226
|
+
"""
|
5227
|
+
Return the value at given coordinates
|
4589
5228
|
|
4590
|
-
|
5229
|
+
:param x: x coordinate
|
5230
|
+
:param y: y coordinate
|
5231
|
+
:param z: z coordinate
|
5232
|
+
:param nullvalue: value to return if the point is outside the array
|
5233
|
+
"""
|
4591
5234
|
|
4592
|
-
|
5235
|
+
if isinstance(self.array.mask, np.bool_):
|
5236
|
+
logging.error(_('Mask is not an array - Please check your data'))
|
5237
|
+
return nullvalue
|
4593
5238
|
|
4594
5239
|
if self.nbdims == 2:
|
4595
5240
|
i, j = self.get_ij_from_xy(x, y)
|
@@ -4600,6 +5245,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4600
5245
|
value = self.array[i, j]
|
4601
5246
|
else:
|
4602
5247
|
value = nullvalue
|
5248
|
+
|
4603
5249
|
elif self.nbdims == 3:
|
4604
5250
|
i, j, k = self.get_ij_from_xy(x, y, z)
|
4605
5251
|
if i >= 0 and i < self.nbx and j >= 0 and j < self.nby and k >= 0 and k < self.nbz:
|
@@ -4611,11 +5257,20 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4611
5257
|
else:
|
4612
5258
|
value = nullvalue
|
4613
5259
|
|
5260
|
+
#FIXME : forcing to convert to float is not a good idea
|
4614
5261
|
return float(value)
|
4615
5262
|
|
4616
|
-
def get_xlim(self, window_x, window_y):
|
4617
|
-
|
4618
|
-
|
5263
|
+
def get_xlim(self, window_x:float, window_y:float):
|
5264
|
+
"""
|
5265
|
+
Return the limits in x for a given window size
|
5266
|
+
|
5267
|
+
:param window_x: window size in x
|
5268
|
+
:param window_y: window size in y
|
5269
|
+
"""
|
5270
|
+
|
5271
|
+
a_x = window_x / (float(self.nbx) * self.dx)
|
5272
|
+
a_y = window_y / (float(self.nby) * self.dy)
|
5273
|
+
|
4619
5274
|
if a_x < a_y:
|
4620
5275
|
# C'est la mise à l'échelle selon x qui compte
|
4621
5276
|
return (self.origx + self.translx, self.origx + self.translx + self.nbx * self.dx)
|
@@ -4625,9 +5280,15 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4625
5280
|
return (self.origx + self.translx + self.nbx * self.dx * 0.5 - l * 0.5,
|
4626
5281
|
self.origx + self.translx + self.nbx * self.dx * 0.5 + l * 0.5)
|
4627
5282
|
|
4628
|
-
def get_ylim(self, window_x, window_y):
|
4629
|
-
|
4630
|
-
|
5283
|
+
def get_ylim(self, window_x:float, window_y:float):
|
5284
|
+
"""
|
5285
|
+
Retrun the limits in y for a given window size
|
5286
|
+
|
5287
|
+
:param window_x: window size in x
|
5288
|
+
:param window_y: window size in y
|
5289
|
+
"""
|
5290
|
+
a_x = window_x / (float(self.nbx) * self.dx)
|
5291
|
+
a_y = window_y / (float(self.nby) * self.dy)
|
4631
5292
|
if a_x < a_y:
|
4632
5293
|
# C'est la mise à l'échelle selon x qui compte
|
4633
5294
|
l = (self.nbx * self.dx) / window_x * window_y
|
@@ -4637,7 +5298,13 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4637
5298
|
# C'est la mise à l'échelle selon y qui compte
|
4638
5299
|
return (self.origy + self.transly, self.origy + self.transly + self.nby * self.dy)
|
4639
5300
|
|
4640
|
-
def get_working_array(self, onzoom=[]):
|
5301
|
+
def get_working_array(self, onzoom:list[float]=[]):
|
5302
|
+
"""
|
5303
|
+
Return the part of the array in the zoom window
|
5304
|
+
|
5305
|
+
:param onzoom: zoom window -- [xmin, xmax, ymin, ymax]
|
5306
|
+
"""
|
5307
|
+
|
4641
5308
|
if onzoom != []:
|
4642
5309
|
istart, jstart = self.get_ij_from_xy(onzoom[0], onzoom[2])
|
4643
5310
|
iend, jend = self.get_ij_from_xy(onzoom[1], onzoom[3])
|
@@ -4653,7 +5320,13 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4653
5320
|
else:
|
4654
5321
|
return self.array[self.array.mask == False]
|
4655
5322
|
|
4656
|
-
def updatepalette(self, which=0, onzoom=[]):
|
5323
|
+
def updatepalette(self, which:int=0, onzoom=[]):
|
5324
|
+
"""
|
5325
|
+
Update the palette/colormap
|
5326
|
+
|
5327
|
+
:param which: which palette to update
|
5328
|
+
:param onzoom: zoom window -- [xmin, xmax, ymin, ymax]
|
5329
|
+
"""
|
4657
5330
|
|
4658
5331
|
if self.array is None:
|
4659
5332
|
return
|
@@ -4677,10 +5350,21 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4677
5350
|
self.rgb[self.array.mask] = [1., 1., 1., 1.]
|
4678
5351
|
|
4679
5352
|
if self.myops is not None:
|
5353
|
+
# update the wx
|
4680
5354
|
self.myops.update_palette()
|
4681
5355
|
|
4682
|
-
def plot(self, sx=None, sy=None, xmin=None, ymin=None, xmax=None, ymax=None, size=None):
|
4683
|
-
|
5356
|
+
def plot(self, sx:float=None, sy:float=None, xmin:float=None, ymin:float=None, xmax:float=None, ymax:float=None, size:float=None):
|
5357
|
+
"""
|
5358
|
+
Plot the array - OpenGL
|
5359
|
+
|
5360
|
+
:param sx: scale along X
|
5361
|
+
:param sy: scale along Y
|
5362
|
+
:param xmin: Lower-Left coordinates in X
|
5363
|
+
:param ymin: Lower-Left coordinates in Y
|
5364
|
+
:param xmax: Upper-Right coordinates in X
|
5365
|
+
:param ymax: Upper-Right coordinates in Y
|
5366
|
+
:param size: size of the window (not used here but necessary for compatibility with Element_To_Draw)
|
5367
|
+
"""
|
4684
5368
|
if not self.plotted:
|
4685
5369
|
return
|
4686
5370
|
|
@@ -4781,6 +5465,8 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4781
5465
|
self.myops.myzones.plot()
|
4782
5466
|
|
4783
5467
|
def delete_lists(self):
|
5468
|
+
""" Delete OpenGL lists """
|
5469
|
+
|
4784
5470
|
for idx, cursize in enumerate(self.mygrid):
|
4785
5471
|
curlist = self.mygrid[cursize]
|
4786
5472
|
nbx = curlist['nbx']
|
@@ -4793,8 +5479,13 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4793
5479
|
self.gridmaxscales = -1
|
4794
5480
|
|
4795
5481
|
def plot_matplotlib(self):
|
5482
|
+
"""
|
5483
|
+
Plot the array - Matplotlib version
|
5484
|
+
|
5485
|
+
Using imshow and RGB array
|
5486
|
+
"""
|
4796
5487
|
|
4797
|
-
self.mask_data(
|
5488
|
+
self.mask_data(self.nullvalue)
|
4798
5489
|
self.updatepalette(0)
|
4799
5490
|
|
4800
5491
|
fig = plt.figure()
|
@@ -4807,6 +5498,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4807
5498
|
plt.show()
|
4808
5499
|
|
4809
5500
|
def fillonecellgrid(self, curscale, loci, locj, force=False):
|
5501
|
+
""" Fill one cell of the plotted grid """
|
4810
5502
|
|
4811
5503
|
cursize = curscale # 2**curscale
|
4812
5504
|
|
@@ -4863,14 +5555,14 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4863
5555
|
|
4864
5556
|
curlist['done'][loci, locj] = 1
|
4865
5557
|
|
4866
|
-
def suxsuy_contour(self, filename='', abs=False) -> tuple[list[int,int], list[int,int], vector, bool]:
|
5558
|
+
def suxsuy_contour(self, filename:str='', abs:bool=False) -> tuple[list[int,int], list[int,int], vector, bool]:
|
4867
5559
|
"""
|
4868
5560
|
The borders are computed on basis of the current *mask*
|
4869
5561
|
|
4870
|
-
|
4871
|
-
|
5562
|
+
:param filename : if provided, write 'sux', 'sux' and 'xy' files
|
5563
|
+
:param abs : add translation coordinates (Global World Coordinates)
|
4872
5564
|
|
4873
|
-
|
5565
|
+
:return indicesX, indicesY, contourgen, interior
|
4874
5566
|
|
4875
5567
|
indicesX : list of coupled indices along X - vertical border - 1-based like Fortran
|
4876
5568
|
indicesY : list of coupled indices along Y - horizontal border - 1-based like Fortran
|
@@ -5058,6 +5750,8 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
5058
5750
|
return WOLF_ARRAY_FULL_SINGLE
|
5059
5751
|
elif curarray.dtype == np.int32:
|
5060
5752
|
return WOLF_ARRAY_FULL_INTEGER
|
5753
|
+
elif curarray.dtype == np.int8:
|
5754
|
+
return WOLF_ARRAY_FULL_INTEGER8
|
5061
5755
|
|
5062
5756
|
self.array = np.ma.array(array.copy())
|
5063
5757
|
self.wolftype = wolftype_from_npz(array)
|
@@ -5066,6 +5760,20 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
5066
5760
|
self.nullvalue = nullvalue
|
5067
5761
|
self.mask_data(self.nullvalue)
|
5068
5762
|
self.reset_plot()
|
5763
|
+
|
5764
|
+
def nullify_border(self, width:int = 1):
|
5765
|
+
"""
|
5766
|
+
Set border to nullvalue
|
5767
|
+
"""
|
5768
|
+
self.array.data[:width,:] = self.nullvalue
|
5769
|
+
self.array.data[-width:,:] = self.nullvalue
|
5770
|
+
self.array.data[:,:width] = self.nullvalue
|
5771
|
+
self.array.data[:,-width:] = self.nullvalue
|
5772
|
+
|
5773
|
+
self.array.mask[:width,:] = True
|
5774
|
+
self.array.mask[-width:,:] = True
|
5775
|
+
self.array.mask[:,:width] = True
|
5776
|
+
self.array.mask[:,-width:] = True
|
5069
5777
|
class WolfArrayMB(WolfArray):
|
5070
5778
|
"""
|
5071
5779
|
Matrice multiblocks
|
@@ -5080,7 +5788,7 @@ class WolfArrayMB(WolfArray):
|
|
5080
5788
|
create=False, mapviewer=None, nullvalue=0, srcheader=None):
|
5081
5789
|
self.myblocks = {}
|
5082
5790
|
super().__init__(fname, mold, masknull, crop, whichtype, preload, create, mapviewer, nullvalue, srcheader)
|
5083
|
-
self.wolftype =
|
5791
|
+
# self.wolftype = whichtype
|
5084
5792
|
|
5085
5793
|
def __getitem__(self, block_key:Union[int,str]) -> WolfArray:
|
5086
5794
|
"""Access a block of this multi-blocks array."""
|
@@ -5094,13 +5802,31 @@ class WolfArrayMB(WolfArray):
|
|
5094
5802
|
else:
|
5095
5803
|
return None
|
5096
5804
|
|
5097
|
-
def add_block(self, arr: WolfArray):
|
5098
|
-
"""
|
5099
|
-
|
5805
|
+
def add_block(self, arr: WolfArray, force_idx:bool=False, copy_array=False):
|
5806
|
+
"""
|
5807
|
+
Adds a properly configured block this multiblock.
|
5808
|
+
|
5809
|
+
:param arr: The block to add.
|
5810
|
+
:param force_idx: If True, the index/key will be set on `arr`. If False, the index/key must already be set on `arr`.
|
5100
5811
|
"""
|
5101
|
-
|
5102
|
-
|
5812
|
+
|
5813
|
+
if copy_array:
|
5814
|
+
arr = WolfArray(mold=arr)
|
5815
|
+
force_idx = True
|
5816
|
+
|
5817
|
+
if force_idx:
|
5818
|
+
arr.idx = getkeyblock(len(self.myblocks))
|
5819
|
+
else:
|
5820
|
+
assert arr.idx is not None and type(arr.idx) == str and arr.idx.strip() != '', f"The block index/key is wrong {arr.idx}"
|
5821
|
+
assert arr.idx not in self.myblocks, "You can't have the same block twice"
|
5822
|
+
pos = len(self.myblocks)
|
5823
|
+
posidx = decodekeyblock(arr.idx, False)
|
5824
|
+
assert pos == posidx, f"The block index/key is wrong {arr.idx}"
|
5825
|
+
|
5103
5826
|
self.myblocks[arr.idx] = arr
|
5827
|
+
|
5828
|
+
arr.isblock = True
|
5829
|
+
arr.blockindex = len(self.myblocks) - 1
|
5104
5830
|
|
5105
5831
|
def share_palette(self):
|
5106
5832
|
"""Partage de la palette de couleurs entre matrices liées"""
|
@@ -5109,7 +5835,8 @@ class WolfArrayMB(WolfArray):
|
|
5109
5835
|
cur.mypal = self.mypal
|
5110
5836
|
cur.link_palette()
|
5111
5837
|
|
5112
|
-
def copy_mask(self, source:"WolfArrayMB", forcenullvalue= False):
|
5838
|
+
def copy_mask(self, source:"WolfArrayMB", forcenullvalue:bool= False):
|
5839
|
+
""" Copy the mask of two arrays """
|
5113
5840
|
|
5114
5841
|
if isinstance(self, type(source)):
|
5115
5842
|
if self.check_consistency(source):
|
@@ -5118,8 +5845,11 @@ class WolfArrayMB(WolfArray):
|
|
5118
5845
|
curblock.copy_mask(curblockother, forcenullvalue)
|
5119
5846
|
i+=1
|
5120
5847
|
self.reset_plot()
|
5848
|
+
else:
|
5849
|
+
logging.warning(_('Copy mask not supported between different types of arrays'))
|
5121
5850
|
|
5122
5851
|
def count(self):
|
5852
|
+
""" Count the number of not null cells """
|
5123
5853
|
|
5124
5854
|
self.nbnotnull = 0
|
5125
5855
|
for i in range(self.nb_blocks):
|
@@ -5130,6 +5860,8 @@ class WolfArrayMB(WolfArray):
|
|
5130
5860
|
self.nbnotnull += nbnotnull
|
5131
5861
|
|
5132
5862
|
def check_plot(self):
|
5863
|
+
""" Check plot and apply to each block """
|
5864
|
+
|
5133
5865
|
self.plotted = True
|
5134
5866
|
self.mimic_plotdata()
|
5135
5867
|
|
@@ -5137,7 +5869,7 @@ class WolfArrayMB(WolfArray):
|
|
5137
5869
|
if os.path.exists(self.filename):
|
5138
5870
|
self.read_data()
|
5139
5871
|
if self.masknull:
|
5140
|
-
self.mask_data(
|
5872
|
+
self.mask_data(self.nullvalue)
|
5141
5873
|
if self.rgb is None:
|
5142
5874
|
self.rgb = np.ones((self.nbx, self.nby, 4), order='F', dtype=np.integer)
|
5143
5875
|
self.updatepalette(0)
|
@@ -5145,33 +5877,69 @@ class WolfArrayMB(WolfArray):
|
|
5145
5877
|
else:
|
5146
5878
|
raise Exception(_(f"Trying to load an array that doesn't exist ({self.filename})"))
|
5147
5879
|
|
5148
|
-
def uncheck_plot(self, unload=True, forceresetOGL=False, askquestion=True):
|
5880
|
+
def uncheck_plot(self, unload:bool=True, forceresetOGL:bool=False, askquestion:bool=True):
|
5881
|
+
""" Uncheck plot and apply to each block """
|
5882
|
+
|
5149
5883
|
self.plotted = False
|
5150
5884
|
self.mimic_plotdata()
|
5151
5885
|
|
5152
5886
|
if unload and self.filename != '':
|
5153
5887
|
if askquestion and not forceresetOGL:
|
5154
|
-
|
5155
|
-
|
5156
|
-
|
5888
|
+
if self.wx_exists:
|
5889
|
+
dlg = wx.MessageDialog(None, _('Do you want to reset OpenGL lists?'), style=wx.YES_NO)
|
5890
|
+
ret = dlg.ShowModal()
|
5891
|
+
if ret == wx.ID_YES:
|
5157
5892
|
forceresetOGL = True
|
5893
|
+
else:
|
5894
|
+
forceresetOGL = True
|
5158
5895
|
|
5159
5896
|
for curblock in self.myblocks.values():
|
5160
5897
|
curblock.uncheck_plot(unload, forceresetOGL, askquestion=False)
|
5161
5898
|
self.rgb = None
|
5899
|
+
|
5162
5900
|
self.myblocks = {}
|
5163
5901
|
self.loaded = False
|
5164
5902
|
|
5165
5903
|
def mask_data(self, value):
|
5166
|
-
|
5167
|
-
curblock = self.myblocks[getkeyblock(i)]
|
5168
|
-
curarray = curblock.array
|
5169
|
-
curarray.mask = curarray.data == value
|
5904
|
+
""" Mask cells where values are equal to `value`"""
|
5170
5905
|
|
5171
|
-
self.
|
5906
|
+
if self.wolftype in [WOLF_ARRAY_FULL_INTEGER, WOLF_ARRAY_FULL_INTEGER16]:
|
5907
|
+
value=int(value)
|
5908
|
+
|
5909
|
+
if value is not None:
|
5910
|
+
|
5911
|
+
for curblock in self.myblocks.values():
|
5912
|
+
curarray = curblock.array
|
5913
|
+
|
5914
|
+
if isinstance(curarray.mask, np.bool_):
|
5915
|
+
# mask is not an array, but a single boolean value
|
5916
|
+
# we must create a new mask array
|
5917
|
+
if np.isnan(value) or math.isnan(value):
|
5918
|
+
curarray.mask = np.isnan(curarray.data)
|
5919
|
+
else:
|
5920
|
+
curarray.mask = curarray.data == value
|
5921
|
+
else:
|
5922
|
+
# Copy to prevent unlinking the mask (see `mask_reset`)
|
5923
|
+
if np.isnan(value) or math.isnan(value):
|
5924
|
+
np.copyto(curarray.mask, np.isnan(curarray.data))
|
5925
|
+
else:
|
5926
|
+
np.copyto(curarray.mask, curarray.data == value)
|
5927
|
+
|
5928
|
+
self.count()
|
5929
|
+
|
5930
|
+
# for i in range(self.nb_blocks):
|
5931
|
+
# curblock = self.myblocks[getkeyblock(i)]
|
5932
|
+
# curarray = curblock.array
|
5933
|
+
# curarray.mask = curarray.data == value
|
5934
|
+
|
5935
|
+
# self.count()
|
5172
5936
|
|
5173
5937
|
def mask_union(self, source:"WolfArrayMB"):
|
5938
|
+
"""
|
5939
|
+
Union of the masks of two arrays
|
5174
5940
|
|
5941
|
+
Applying for each block iteratively.
|
5942
|
+
"""
|
5175
5943
|
if isinstance(self, type(source)):
|
5176
5944
|
if self.check_consistency(source):
|
5177
5945
|
i=0
|
@@ -5181,14 +5949,22 @@ class WolfArrayMB(WolfArray):
|
|
5181
5949
|
self.reset_plot()
|
5182
5950
|
|
5183
5951
|
def read_data(self):
|
5952
|
+
""" Lecture du tableau en binaire """
|
5953
|
+
|
5184
5954
|
with open(self.filename, 'rb') as f:
|
5185
5955
|
for i in range(self.nb_blocks):
|
5186
|
-
|
5956
|
+
|
5957
|
+
if self.wolftype == WOLF_ARRAY_MB_SINGLE:
|
5958
|
+
curblock = WolfArray(whichtype=WOLF_ARRAY_FULL_SINGLE, srcheader=self.head_blocks[getkeyblock(i)])
|
5959
|
+
elif self.wolftype == WOLF_ARRAY_MB_INTEGER:
|
5960
|
+
curblock = WolfArray(whichtype=WOLF_ARRAY_FULL_INTEGER)
|
5961
|
+
|
5187
5962
|
curblock.isblock = True
|
5188
5963
|
curblock.blockindex = i
|
5189
5964
|
curblock.idx = getkeyblock(i)
|
5190
|
-
|
5965
|
+
|
5191
5966
|
curblock._read_binary_data(f)
|
5967
|
+
|
5192
5968
|
self.myblocks[getkeyblock(i)] = curblock
|
5193
5969
|
|
5194
5970
|
def write_array(self):
|
@@ -5199,9 +5975,31 @@ class WolfArrayMB(WolfArray):
|
|
5199
5975
|
f.write(curarray.array.data.transpose().tobytes())
|
5200
5976
|
|
5201
5977
|
def get_ij_from_xy(self, x:float, y:float, z:float=0., scale:float=1., aswolf:bool=False, abs:bool=True, which_block:int=1):
|
5978
|
+
"""
|
5979
|
+
alias for get_ij_from_xy for the block `which_block
|
5980
|
+
|
5981
|
+
:param x: x coordinate
|
5982
|
+
:param y: y coordinate
|
5983
|
+
:param z: z coordinate
|
5984
|
+
:param scale: scale factor
|
5985
|
+
:param aswolf: if True, then the indices are 1-based like Fortran, otherwise 0-based like Python
|
5986
|
+
:param abs: if True, then the translation is taken into account
|
5987
|
+
:param which_block: block index 1-based
|
5988
|
+
"""
|
5202
5989
|
return self.myblocks[getkeyblock(which_block, False)].get_ij_from_xy(x, y, z, scale, aswolf, abs)
|
5203
5990
|
|
5204
|
-
def get_values_as_wolf(self, i, j, which_block=1):
|
5991
|
+
def get_values_as_wolf(self, i:int, j:int, which_block:int=1):
|
5992
|
+
"""
|
5993
|
+
Return the value at indices (i,j) of the block `which_block.
|
5994
|
+
|
5995
|
+
:param i: i index
|
5996
|
+
:param j: j index
|
5997
|
+
:param which_block: block index 1-based
|
5998
|
+
"""
|
5999
|
+
h = np.NaN
|
6000
|
+
if which_block == 0:
|
6001
|
+
logging.warning("Block index is probably 0-based. It should be 1-based.")
|
6002
|
+
return h
|
5205
6003
|
|
5206
6004
|
keyblock = getkeyblock(which_block, False)
|
5207
6005
|
curblock = self.myblocks[keyblock]
|
@@ -5214,13 +6012,20 @@ class WolfArrayMB(WolfArray):
|
|
5214
6012
|
|
5215
6013
|
return h
|
5216
6014
|
|
5217
|
-
def get_value(self, x, y, abs=True):
|
5218
|
-
"""
|
6015
|
+
def get_value(self, x:float, y:float, abs:bool=True):
|
6016
|
+
"""
|
6017
|
+
Read the value at world coordinate (x,y). if `abs` is
|
5219
6018
|
given, then the translation is is taken into account.
|
5220
6019
|
|
5221
6020
|
If no block covers the coordinate, then np.NaN is returned
|
5222
6021
|
If several blocks cover the given coordinate then the first
|
5223
6022
|
match is returned (and thus, the others are ignored).
|
6023
|
+
|
6024
|
+
:param x: x coordinate
|
6025
|
+
:param y: y coordinate
|
6026
|
+
:param abs: if True, then the translation is taken into account
|
6027
|
+
|
6028
|
+
:return: the value at (x,y) or np.NaN if no block covers the coordinate
|
5224
6029
|
"""
|
5225
6030
|
|
5226
6031
|
h = np.NaN
|
@@ -5238,13 +6043,37 @@ class WolfArrayMB(WolfArray):
|
|
5238
6043
|
|
5239
6044
|
return h
|
5240
6045
|
|
5241
|
-
def get_xy_from_ij(self, i, j, which_block, aswolf=False, abs=True):
|
6046
|
+
def get_xy_from_ij(self, i:int, j:int, which_block:int, aswolf:bool=False, abs:bool=True):
|
6047
|
+
"""
|
6048
|
+
Return the world coordinates (x,y) of the indices (i,j) of the block `which_block.
|
6049
|
+
|
6050
|
+
:param i: i index -- 1-based like Fortran or 0-based like Python, see 'aswolf' parameter
|
6051
|
+
:param j: j index -- 1-based like Fortran or 0-based like Python, see 'aswolf' parameter
|
6052
|
+
:param which_block: block index 1-based
|
6053
|
+
:param aswolf: if True, (i,j) are 1-based like Fortran, otherwise 0-based like Python
|
6054
|
+
:param abs: if True, then the translation is taken into account
|
6055
|
+
"""
|
6056
|
+
|
6057
|
+
if which_block == 0:
|
6058
|
+
logging.warning("Block index is probably 0-based. It should be 1-based.")
|
6059
|
+
return
|
6060
|
+
|
5242
6061
|
k = getkeyblock(which_block, False)
|
5243
6062
|
assert k in self.myblocks, f"The block '{k}' you ask for doesn't exist."
|
6063
|
+
|
5244
6064
|
x, y = self.myblocks[k].get_xy_from_ij(i, j, aswolf=aswolf, abs=abs)
|
5245
6065
|
return x, y
|
5246
6066
|
|
5247
|
-
def get_blockij_from_xy(self, x, y, abs=True):
|
6067
|
+
def get_blockij_from_xy(self, x:float, y:float, abs:bool=True):
|
6068
|
+
"""
|
6069
|
+
Return the block indices (i,j) of the block covering the world coordinate (x,y)
|
6070
|
+
|
6071
|
+
:param x: x coordinate
|
6072
|
+
:param y: y coordinate
|
6073
|
+
:param abs: if True, then the translation is taken into account
|
6074
|
+
|
6075
|
+
:return: the block indices (i,j,[k]) or (-1,-1,-1) if no block covers the coordinate
|
6076
|
+
"""
|
5248
6077
|
|
5249
6078
|
exists = False
|
5250
6079
|
k = 1
|
@@ -5267,11 +6096,19 @@ class WolfArrayMB(WolfArray):
|
|
5267
6096
|
return -1, -1, -1
|
5268
6097
|
|
5269
6098
|
def link_palette(self):
|
5270
|
-
"""
|
6099
|
+
"""Lier les palettes des blocs à la palette de l'objet parent"""
|
6100
|
+
|
5271
6101
|
for curblock in self.myblocks.values():
|
5272
6102
|
curblock.mypal = self.mypal
|
5273
6103
|
|
5274
|
-
def updatepalette(self, which=0, onzoom=[]):
|
6104
|
+
def updatepalette(self, which:int=0, onzoom:list[float]=[]):
|
6105
|
+
"""
|
6106
|
+
Update the palette/colormap of the array
|
6107
|
+
|
6108
|
+
:param which: which colormap to use
|
6109
|
+
:param onzoom: if not empty, then only the values within the zoom are used to update the palette -- [xmin,xmax,ymin,ymax]
|
6110
|
+
|
6111
|
+
"""
|
5275
6112
|
|
5276
6113
|
if len(self.myblocks) == 0:
|
5277
6114
|
return
|
@@ -5308,17 +6145,19 @@ class WolfArrayMB(WolfArray):
|
|
5308
6145
|
self.myops.update_palette()
|
5309
6146
|
|
5310
6147
|
def delete_lists(self):
|
6148
|
+
""" Delete OpenGL lists """
|
5311
6149
|
for curblock in self.myblocks.values():
|
5312
6150
|
curblock.delete_lists()
|
5313
6151
|
|
5314
6152
|
def mimic_plotdata(self):
|
6153
|
+
""" Copy plot flags to children """
|
5315
6154
|
for curblock in self.myblocks.values():
|
5316
6155
|
curblock: WolfArray
|
5317
6156
|
curblock.plotted = self.plotted
|
5318
6157
|
curblock.plotting = self.plotting
|
5319
6158
|
|
5320
6159
|
def plot(self, sx=None, sy=None, xmin=None, ymin=None, xmax=None, ymax=None):
|
5321
|
-
|
6160
|
+
""" Plot the array """
|
5322
6161
|
self.plotting = True
|
5323
6162
|
self.mimic_plotdata()
|
5324
6163
|
|
@@ -5332,8 +6171,8 @@ class WolfArrayMB(WolfArray):
|
|
5332
6171
|
for curblock in self.myblocks.values():
|
5333
6172
|
curblock.fillonecellgrid(curscale, loci, locj, force)
|
5334
6173
|
|
5335
|
-
def check_consistency(self,other):
|
5336
|
-
|
6174
|
+
def check_consistency(self, other):
|
6175
|
+
""" Vérifie la cohérence entre deux matrices """
|
5337
6176
|
test = isinstance(self, type(other))
|
5338
6177
|
|
5339
6178
|
if test:
|
@@ -5502,6 +6341,7 @@ class WolfArrayMB(WolfArray):
|
|
5502
6341
|
return newArray
|
5503
6342
|
|
5504
6343
|
def reset(self):
|
6344
|
+
""" Reset each block"""
|
5505
6345
|
for i in range(self.nb_blocks):
|
5506
6346
|
self[i].reset()
|
5507
6347
|
|
@@ -5632,7 +6472,19 @@ class WolfArrayMB(WolfArray):
|
|
5632
6472
|
|
5633
6473
|
return fig,ax
|
5634
6474
|
|
5635
|
-
|
6475
|
+
def allocate_ressources(self):
|
6476
|
+
""" Allocate memory ressources """
|
6477
|
+
|
6478
|
+
if len(self.myblocks)==0:
|
6479
|
+
for id, (key, curhead) in enumerate(self.head_blocks.items()):
|
6480
|
+
if self.wolftype == WOLF_ARRAY_MB_SINGLE:
|
6481
|
+
self.myblocks[key] = WolfArray(srcheader=curhead, whichtype=WOLF_ARRAY_FULL_SINGLE)
|
6482
|
+
elif self.wolftype == WOLF_ARRAY_MB_INTEGER:
|
6483
|
+
self.myblocks[key] = WolfArray(srcheader=curhead, whichtype=WOLF_ARRAY_FULL_INTEGER)
|
6484
|
+
|
6485
|
+
self.myblocks[key].isblock = True
|
6486
|
+
self.myblocks[key].blockindex = id
|
6487
|
+
self.myblocks[key].idx = key
|
5636
6488
|
class WolfArrayMNAP(WolfArrayMB):
|
5637
6489
|
"""
|
5638
6490
|
Matrice MNAP d'une modélisation WOLF2D
|
@@ -5678,8 +6530,6 @@ class WolfArrayMNAP(WolfArrayMB):
|
|
5678
6530
|
v : wolfvertex
|
5679
6531
|
f.write(padf(v.x) + padf(v.y) + "\n")
|
5680
6532
|
|
5681
|
-
|
5682
|
-
|
5683
6533
|
def read_data(self):
|
5684
6534
|
if os.path.exists(self.filename + '.mnap'):
|
5685
6535
|
with open(self.filename + '.mnap') as f:
|
@@ -5778,21 +6628,35 @@ class WolfArray_Sim2D(WolfArray):
|
|
5778
6628
|
"""
|
5779
6629
|
Surcharge de WolfArray pour les matrices fines de simulation
|
5780
6630
|
Objectif :
|
5781
|
-
-
|
6631
|
+
- lier la matrice de mask à une source commune
|
5782
6632
|
"""
|
5783
|
-
|
5784
|
-
|
5785
|
-
|
5786
|
-
|
5787
|
-
|
5788
|
-
|
6633
|
+
def __init__(self,
|
6634
|
+
fname:str=None,
|
6635
|
+
mold:"WolfArray"=None,
|
6636
|
+
masknull:bool=True,
|
6637
|
+
crop:list[float]=None,
|
6638
|
+
whichtype=WOLF_ARRAY_FULL_SINGLE,
|
6639
|
+
preload:bool=True,
|
6640
|
+
create:bool=False,
|
6641
|
+
mapviewer=None,
|
6642
|
+
nullvalue:float=0,
|
6643
|
+
srcheader:header_wolf=None,
|
6644
|
+
masksrc:np.ndarray=None):
|
6645
|
+
|
6646
|
+
# link to mask source
|
6647
|
+
self.masksrc = masksrc
|
5789
6648
|
|
5790
6649
|
# FIXME __init__ will initialize a mask of its own and so self.masksrc
|
5791
6650
|
# will be ignored at this point. That's misleading, I'd thought
|
5792
6651
|
# that passing a mask would wire it to this array, forever.
|
5793
|
-
super().__init__(fname, mold, masknull, crop, whichtype, preload, create, mapviewer, nullvalue, srcheader)
|
6652
|
+
super().__init__(fname, mold, masknull, crop, whichtype, preload, create, mapviewer, nullvalue, srcheader, mask_source=masksrc)
|
5794
6653
|
|
5795
6654
|
def check_plot(self):
|
6655
|
+
"""
|
6656
|
+
Surcharge de la fonction de vérification du plot
|
6657
|
+
|
6658
|
+
Utile notamment pour lier le masque
|
6659
|
+
"""
|
5796
6660
|
self.plotted = True
|
5797
6661
|
|
5798
6662
|
if not self.loaded and self.filename != '':
|
@@ -5804,7 +6668,7 @@ class WolfArray_Sim2D(WolfArray):
|
|
5804
6668
|
return
|
5805
6669
|
|
5806
6670
|
if self.masksrc is not None:
|
5807
|
-
|
6671
|
+
self.array.mask = self.masksrc
|
5808
6672
|
|
5809
6673
|
self.loaded = True
|
5810
6674
|
|
@@ -5812,6 +6676,12 @@ class WolfArray_Sim2D(WolfArray):
|
|
5812
6676
|
self.updatepalette(0)
|
5813
6677
|
|
5814
6678
|
def read_all(self):
|
6679
|
+
"""
|
6680
|
+
Surcharge de la fonction de lecture de la matrice
|
6681
|
+
|
6682
|
+
Utile notamment puor le fichier zbin
|
6683
|
+
"""
|
6684
|
+
|
5815
6685
|
if self.filename[-4:]=='zbin':
|
5816
6686
|
fileold = self.filename
|
5817
6687
|
|
@@ -5827,6 +6697,11 @@ class WolfArray_Sim2D(WolfArray):
|
|
5827
6697
|
return super().read_all()
|
5828
6698
|
|
5829
6699
|
def read_data(self):
|
6700
|
+
"""
|
6701
|
+
Surcharge de la fonction de lecture de la matrice
|
6702
|
+
|
6703
|
+
Utile notamment puor le fichier zbin
|
6704
|
+
"""
|
5830
6705
|
|
5831
6706
|
if self.filename[-4:]=='zbin':
|
5832
6707
|
fileold = self.filename
|
@@ -5859,6 +6734,11 @@ class WolfArray_Sim2D(WolfArray):
|
|
5859
6734
|
return super().write_all()
|
5860
6735
|
|
5861
6736
|
def write_array(self):
|
6737
|
+
"""
|
6738
|
+
Surcharge de la fonction d'écriture de la matrice
|
6739
|
+
|
6740
|
+
Utile notamment puor le fichier zbin
|
6741
|
+
"""
|
5862
6742
|
if self.filename[-4:]=='zbin':
|
5863
6743
|
fileold = self.filename
|
5864
6744
|
|