wolfhece 2.1.107__py3-none-any.whl → 2.1.109__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/pybridges.py CHANGED
@@ -48,10 +48,18 @@ class stored_values_coords(Enum):
48
48
  X = (0, 'CoordX')
49
49
  Y = (1, 'CoordY')
50
50
 
51
- class zones_in_file(Enum):
51
+ class zones_in_file_fr_vec(Enum):
52
52
  PARTS = '3 zones'
53
53
  RIVER = 'entier'
54
- SECTION = 'section'
54
+
55
+ class zones_in_file(Enum):
56
+ PARTS = _('bridge_position')
57
+ RIVER = _('river')
58
+ DECK = _('deck')
59
+ ROOF = _('roof')
60
+ PIER = _('pier')
61
+ CROSS_SECTIONS = _('crosssections')
62
+ EXTRACTION = _('extraction')
55
63
 
56
64
  class operators(Enum):
57
65
  MEDIAN = 'median'
@@ -66,6 +74,16 @@ class parts_values(Enum):
66
74
  UPSTREAM = _('upstream')
67
75
  DOWNSTREAM = _('downstream')
68
76
 
77
+ class rivers_values(Enum):
78
+ RIVERBED = _('riverbed')
79
+ LEFTBANK = _('leftbank')
80
+ RIGHTBANK = _('rightbank')
81
+
82
+ class cs_values(Enum):
83
+ UPSTREAM = _('upstream')
84
+ MIDDLE = _('middle')
85
+ DOWNSTREAM = _('downstream')
86
+
69
87
  class Bridge(Zones):
70
88
  """
71
89
  Bridge class
@@ -105,108 +123,230 @@ class Bridge(Zones):
105
123
 
106
124
  """
107
125
 
126
+ @classmethod
127
+ def new_bridge(cls, name:str):
128
+ """
129
+ Create a new bridge with name
130
+ """
131
+ new_bridge = cls()
132
+ new_bridge.myname = name
133
+
134
+ position = zone(name = zones_in_file.PARTS.value, parent= new_bridge)
135
+ new_bridge.add_zone(position)
136
+
137
+ new_bridge.centralpart = vector(name = parts_values.CENTRAL.value)
138
+ position.add_vector(new_bridge.centralpart, forceparent=True)
139
+
140
+ new_bridge.upstream = vector(name = parts_values.UPSTREAM.value)
141
+ position.add_vector(new_bridge.upstream, forceparent=True)
142
+
143
+ new_bridge.downstream = vector(name = parts_values.DOWNSTREAM.value)
144
+ position.add_vector(new_bridge.downstream, forceparent=True)
145
+
146
+ river = zone(name = zones_in_file.RIVER.value, parent= new_bridge)
147
+ new_bridge.add_zone(river)
148
+
149
+ new_bridge.leftbank = vector(name = rivers_values.LEFTBANK.value)
150
+ new_bridge.riverbed = vector(name = rivers_values.RIVERBED.value)
151
+ new_bridge.rightbank = vector(name = rivers_values.RIGHTBANK.value)
152
+
153
+ river.add_vector(new_bridge.leftbank, forceparent=True)
154
+ river.add_vector(new_bridge.riverbed, forceparent=True)
155
+ river.add_vector(new_bridge.rightbank, forceparent=True)
156
+
157
+ new_bridge.add_zone(zone(name = zones_in_file.DECK.value, parent= new_bridge))
158
+ new_bridge.add_zone(zone(name = zones_in_file.ROOF.value, parent= new_bridge))
159
+ new_bridge.add_zone(zone(name = zones_in_file.PIER.value, parent= new_bridge))
160
+ new_bridge.add_zone(zone(name = zones_in_file.CROSS_SECTIONS.value, parent= new_bridge))
161
+ new_bridge.add_zone(zone(name = zones_in_file.EXTRACTION.value, parent= new_bridge))
162
+
163
+ return new_bridge
164
+
108
165
  def __init__(self, myfile='', ds:float=5., ox: float = 0, oy: float = 0, tx: float = 0, ty: float = 0, parent=None, is2D=True, wx_exists:bool = False):
109
166
  super().__init__(myfile, ox, oy, tx, ty, parent, is2D, wx_exists)
110
167
  self.init_ui()
111
168
 
112
- self.myname = splitext(basename(myfile))[0]
169
+ self.centralpart = None
170
+ self.upstream = None
171
+ self.downstream = None
113
172
 
114
- # recherche de la zone du fichier contenant les 3 parties de l'ouvrage
115
- curzone = self.get_zone(zones_in_file.PARTS.value)
116
- if curzone is None:
117
- curzone = self.get_zone(0)
118
- curzone.myname = zones_in_file.PARTS.value # on force le nom de la zone pour éviter de refaire le test ailleurs
119
- if curzone is None:
120
- raise Warning(_('Bad file : {}'.format(myfile)))
173
+ self.riverbed = None
174
+ self.leftbank = None
175
+ self.rightbank = None
121
176
 
122
- # attribution des vecteurs pour les différentes parties de l'ouvrage
177
+ self.polygons_zone = None
123
178
 
124
- self.centralpart = curzone.get_vector('tablier') # 4 vertices from Upstream Left to Dowstream Left passing by Upstream Right and Downstream Right
125
- if self.centralpart is None:
126
- self.centralpart = curzone.get_vector('seuil') # 4 vertices from Upstream Left to Dowstream Left passing by Upstream Right and Downstream Right
179
+ if myfile != '':
180
+ self.myname = splitext(basename(myfile))[0]
181
+ extension = splitext(basename(myfile))[1]
127
182
 
128
- self.upstream = curzone.get_vector('amont') # 4 vertices from Upstream Left Deck to Upstream Right Deck passing by Upstream Left Bank and Upstream Right Bank
129
- self.downstream = curzone.get_vector('aval') # 4 vertices from Downstream Left Deck Left to Downstream Right Deck passing by Downstream Left Bank and Downstream Right Bank
130
183
 
131
- xydeck = self.centralpart.asnparray()
184
+ if extension == '.vec':
132
185
 
133
- # point central de l'ouvrage
134
- self.centerx = np.mean(xydeck[:,0]) # X coordinate of the deck
135
- self.centery = np.mean(xydeck[:,1]) # X coordinate of the deck
136
- self.curvi = 0 # s curvilinear coordinate of the deck along a support polyline
186
+ # recherche de la zone du fichier contenant les 3 parties de l'ouvrage
187
+ curzone = self.get_zone(zones_in_file_fr_vec.PARTS.value)
188
+ if curzone is None:
189
+ curzone = self.get_zone(0)
190
+ curzone.myname = zones_in_file_fr_vec.PARTS.value # on force le nom de la zone pour éviter de refaire le test ailleurs
191
+ if curzone is None:
192
+ raise Warning(_('Bad file : {}'.format(myfile)))
137
193
 
138
- """
139
- Si certaines parties ne sont pas attribuées, il peut s'agir d'une mauvaise appellation.
140
- Dans ce cas, on attribue sur base de la position dans la zone
141
- """
142
- assert curzone.nbvectors==3, _('Bad number of parts')
143
-
144
- if self.centralpart is None:
145
- self.centralpart = curzone.get_vector(0)
146
- if self.upstream is None:
147
- self.upstream = curzone.get_vector(1)
148
- if self.downstream is None:
149
- self.downstream = curzone.get_vector(2)
150
-
151
- if self.centralpart is None:
152
- raise Warning(_('Bad file : {}'.format(myfile)))
153
- if self.upstream is None:
154
- raise Warning(_('Bad file : {}'.format(myfile)))
155
- if self.downstream is None:
156
- raise Warning(_('Bad file : {}'.format(myfile)))
157
-
158
- curzone = self.get_zone(zones_in_file.RIVER.value)
159
- if curzone is None:
160
- curzone = self.get_zone(1)
161
- curzone.myname = zones_in_file.RIVER.value # on force le nom de la zone pour éviter de refaire le test ailleurs
162
- if curzone is None:
163
- raise Warning(_('Bad file : {}'.format(myfile)))
164
-
165
- self.riverbed = curzone.get_vector('parallèle') # vertices from upstream to downstream
166
- if self.riverbed is None:
167
- self.riverbed = curzone.get_vector(1)
168
- if self.riverbed is None:
169
- raise Warning(_('Bad file : {}'.format(myfile)))
170
-
171
- self.riverbed.reverse()
172
-
173
- self.leftbank = curzone.get_vector(2) # vertices from upstream to downstream
174
- if self.leftbank is None:
175
- raise Warning(_('Bad file : {}'.format(myfile)))
176
-
177
- self.leftbank.reverse()
178
-
179
- self.rightbank = curzone.get_vector(0) # vertices from upstream to downstream
180
- if self.rightbank is None:
181
- raise Warning(_('Bad file : {}'.format(myfile)))
182
-
183
- self.rightbank.reverse()
184
-
185
- curzone.myvectors = [self.leftbank, self.riverbed, self.rightbank] #inverse order to be up -> down
186
-
187
- #création des polygones de rivière
188
- curzone.create_polygon_from_parallel(ds)
189
- self.polygons_zone:zone
190
- self.polygons_zone = self.get_zone(-1)
191
- self.polygons_curvi = {}
192
- for curvert in self.polygons_zone.myvectors:
193
- self.polygons_curvi[curvert.myname] = curvert.myvertices[0].z
194
+ # attribution des vecteurs pour les différentes parties de l'ouvrage
195
+
196
+ self.centralpart = curzone.get_vector('tablier') # 4 vertices from Upstream Left to Dowstream Left passing by Upstream Right and Downstream Right
197
+ if self.centralpart is None:
198
+ self.centralpart = curzone.get_vector('seuil') # 4 vertices from Upstream Left to Dowstream Left passing by Upstream Right and Downstream Right
199
+
200
+ self.upstream = curzone.get_vector('amont') # 4 vertices from Upstream Left Deck to Upstream Right Deck passing by Upstream Left Bank and Upstream Right Bank
201
+ self.downstream = curzone.get_vector('aval') # 4 vertices from Downstream Left Deck Left to Downstream Right Deck passing by Downstream Left Bank and Downstream Right Bank
202
+
203
+ xydeck = self.centralpart.asnparray()
204
+
205
+ # point central de l'ouvrage
206
+ self.centerx = np.mean(xydeck[:,0]) # X coordinate of the deck
207
+ self.centery = np.mean(xydeck[:,1]) # X coordinate of the deck
208
+ self.curvi = 0 # s curvilinear coordinate of the deck along a support polyline
209
+
210
+ """
211
+ Si certaines parties ne sont pas attribuées, il peut s'agir d'une mauvaise appellation.
212
+ Dans ce cas, on attribue sur base de la position dans la zone
213
+ """
214
+ assert curzone.nbvectors==3, _('Bad number of parts')
215
+
216
+ if self.centralpart is None:
217
+ self.centralpart = curzone.get_vector(0)
218
+ if self.upstream is None:
219
+ self.upstream = curzone.get_vector(1)
220
+ if self.downstream is None:
221
+ self.downstream = curzone.get_vector(2)
222
+
223
+ if self.centralpart is None:
224
+ raise Warning(_('Bad file : {}'.format(myfile)))
225
+ if self.upstream is None:
226
+ raise Warning(_('Bad file : {}'.format(myfile)))
227
+ if self.downstream is None:
228
+ raise Warning(_('Bad file : {}'.format(myfile)))
229
+
230
+ curzone = self.get_zone(zones_in_file_fr_vec.RIVER.value)
231
+ if curzone is None:
232
+ curzone = self.get_zone(1)
233
+ curzone.myname = zones_in_file_fr_vec.RIVER.value # on force le nom de la zone pour éviter de refaire le test ailleurs
234
+ if curzone is None:
235
+ raise Warning(_('Bad file : {}'.format(myfile)))
194
236
 
195
- for vec in self.polygons_zone.myvectors:
196
- vec.myprop.used=False # cache les polygones pour ne pas surcharger l'affichage éventuel
237
+ self.riverbed = curzone.get_vector('parallèle') # vertices from upstream to downstream
238
+ if self.riverbed is None:
239
+ self.riverbed = curzone.get_vector(1)
240
+ if self.riverbed is None:
241
+ raise Warning(_('Bad file : {}'.format(myfile)))
242
+
243
+ self.riverbed.reverse()
244
+
245
+ self.leftbank = curzone.get_vector(2) # vertices from upstream to downstream
246
+ if self.leftbank is None:
247
+ raise Warning(_('Bad file : {}'.format(myfile)))
248
+
249
+ self.leftbank.reverse()
250
+
251
+ self.rightbank = curzone.get_vector(0) # vertices from upstream to downstream
252
+ if self.rightbank is None:
253
+ raise Warning(_('Bad file : {}'.format(myfile)))
254
+
255
+ self.rightbank.reverse()
256
+
257
+ elif extension == '.vecz':
258
+
259
+ zone_names = [curzone.myname for curzone in self.myzones]
260
+
261
+ # test if all zones are present
262
+ for curkey in zones_in_file:
263
+ if curkey.value not in zone_names:
264
+ logging.warning(_('Zone {} not found in file {}'.format(curkey.value, myfile)))
265
+
266
+
267
+ if zones_in_file.PARTS.value in zone_names:
268
+ # recherche de la zone du fichier contenant les 3 parties de l'ouvrage
269
+ curzone = self.get_zone(zones_in_file.PARTS.value)
270
+
271
+ vec_names = [curvec.myname for curvec in curzone.myvectors]
272
+ for curkey in parts_values:
273
+ if curkey.value not in vec_names:
274
+ logging.error(_('Vector {} not found in zone {}'.format(curkey.value, zones_in_file.PARTS.value)))
275
+
276
+ # attribution des vecteurs pour les différentes parties de l'ouvrage
277
+ self.centralpart = curzone.get_vector(parts_values.CENTRAL.value) # 4 vertices from Upstream Left to Dowstream Left passing by Upstream Right and Downstream Right
278
+ self.upstream = curzone.get_vector(parts_values.UPSTREAM.value) # 4 vertices from Upstream Left Deck to Upstream Right Deck passing by Upstream Left Bank and Upstream Right Bank
279
+ self.downstream = curzone.get_vector(parts_values.DOWNSTREAM.value) # 4 vertices from Downstream Left Deck Left to Downstream Right Deck passing by Downstream Left Bank and Downstream Right Bank
280
+
281
+ xydeck = self.centralpart.asnparray()
282
+
283
+ # point central de l'ouvrage
284
+ self.centerx = np.mean(xydeck[:,0]) # X coordinate of the deck
285
+ self.centery = np.mean(xydeck[:,1]) # X coordinate of the deck
286
+ self.curvi = 0 # s curvilinear coordinate of the deck along a support polyline
287
+
288
+ if self.centralpart is None:
289
+ raise Warning(_('Bad file : {}'.format(myfile)))
290
+ if self.upstream is None:
291
+ raise Warning(_('Bad file : {}'.format(myfile)))
292
+ if self.downstream is None:
293
+ raise Warning(_('Bad file : {}'.format(myfile)))
294
+
295
+ if zones_in_file.RIVER.value in zone_names:
296
+ curzone = self.get_zone(zones_in_file.RIVER.value)
297
+
298
+ self.riverbed = curzone.get_vector(rivers_values.RIVERBED.value) # vertices from upstream to downstream
299
+ self.leftbank = curzone.get_vector(rivers_values.LEFTBANK.value) # vertices from upstream to downstream
300
+ self.rightbank = curzone.get_vector(rivers_values.RIGHTBANK.value) # vertices from upstream to downstream
301
+
302
+ if self.riverbed is None:
303
+ raise Warning(_('Bad file : {}'.format(myfile)))
304
+ if self.leftbank is None:
305
+ raise Warning(_('Bad file : {}'.format(myfile)))
306
+ if self.rightbank is None:
307
+ raise Warning(_('Bad file : {}'.format(myfile)))
308
+
309
+ self.create_polygon_river(ds)
310
+ self.force_plot()
311
+
312
+ self.colorize()
313
+
314
+ def force_plot(self):
197
315
 
198
316
  vecs = [self.centralpart, self.upstream, self.downstream, self.riverbed, self.leftbank, self.rightbank]
199
317
  vec: vector
200
318
  for vec in vecs:
201
- vec.myprop.used=True
319
+ if vec is not None:
320
+ vec.myprop.used=True
202
321
 
203
- self.colorize()
322
+ def create_polygon_river(self, ds:float=5.):
323
+ """ Create river polygons """
324
+
325
+ if self.leftbank is not None and self.riverbed is not None and self.rightbank is not None:
326
+
327
+ self.polygons_zone = zone(name= "polygons_river")
328
+ self.add_zone(self.polygons_zone, forceparent=True)
329
+ self.polygons_zone.myvectors = [self.leftbank, self.riverbed, self.rightbank] #inverse order to be up -> down
330
+
331
+ #création des polygones de rivière
332
+ self.polygons_zone.create_polygon_from_parallel(ds)
333
+
334
+ self.polygons_zone = self.get_zone(-1)
335
+ self.polygons_curvi = {}
336
+ for curvert in self.polygons_zone.myvectors:
337
+ self.polygons_curvi[curvert.myname] = curvert.myvertices[0].z
338
+
339
+ for vec in self.polygons_zone.myvectors:
340
+ vec.myprop.used=False # cache les polygones pour ne pas surcharger l'affichage éventuel
204
341
 
205
342
  def colorize(self):
206
343
  """Colorisation des polygones pour l'interface graphique"""
207
- self.centralpart.myprop.color = getIfromRGB((0,255,0))
208
- self.upstream.myprop.color = getIfromRGB((255,0,0))
209
- self.downstream.myprop.color = getIfromRGB((0,0,255))
344
+
345
+ if self.centralpart is not None and self.upstream is not None and self.downstream is not None:
346
+
347
+ self.centralpart.myprop.color = getIfromRGB((0,255,0))
348
+ self.upstream.myprop.color = getIfromRGB((255,0,0))
349
+ self.downstream.myprop.color = getIfromRGB((0,0,255))
210
350
 
211
351
  def get_distance(self, x:float, y:float):
212
352
  """
@@ -260,7 +400,7 @@ class Bridge(Zones):
260
400
  ATTENTION : si linked_arrays est un dictionnaire, alors un niveau supérieur est ajouté sur base des clés de ce dictionnaire, dans ce cas, self.linked est un dict et non une liste
261
401
 
262
402
  """
263
- curzone = self.get_zone(zones_in_file.PARTS.value)
403
+ curzone = self.get_zone(zones_in_file_fr_vec.PARTS.value)
264
404
 
265
405
  if isinstance(linked_arrays, dict):
266
406
 
@@ -1314,8 +1454,8 @@ class Weir(Bridge):
1314
1454
 
1315
1455
  def colorize(self):
1316
1456
  self.centralpart.myprop.color = getIfromRGB((102,102,255))
1317
- self.upstream.myprop.color = getIfromRGB((255,0,127))
1318
- self.downstream.myprop.color = getIfromRGB((102,0,204))
1457
+ self.upstream.myprop.color = getIfromRGB((255,0,127))
1458
+ self.downstream.myprop.color = getIfromRGB((102,0,204))
1319
1459
 
1320
1460
  class Weirs(Bridges):
1321
1461
 
@@ -202,7 +202,7 @@ class Config_Manager_2D_GPU:
202
202
  Gestionnaire de configurations 2D - code GPU
203
203
  """
204
204
 
205
- def __init__(self, workingdir:str = '', mapviewer:WolfMapViewer = None, python_venv:Path = None) -> None:
205
+ def __init__(self, workingdir:str = '', mapviewer:WolfMapViewer = None, python_venv:Path = None, create_ui_if_wx:bool = False) -> None:
206
206
  """
207
207
  Recherche de toutes les modélisation dans un répertoire et ses sous-répertoires
208
208
  """
@@ -235,6 +235,7 @@ class Config_Manager_2D_GPU:
235
235
 
236
236
  self._txtctrl = None
237
237
  self._ui = None
238
+ self._create_ui_if_wx = create_ui_if_wx
238
239
 
239
240
  self._epsilon = 0.01
240
241
  self._filter_independent = True
@@ -287,7 +288,7 @@ class Config_Manager_2D_GPU:
287
288
  # la fenêtre est déjà ouverte
288
289
  self._ui.refill_data(self.configs)
289
290
  else:
290
- if self.wx_exists:
291
+ if self.wx_exists and self._create_ui_if_wx:
291
292
  self._ui = UI_Manager_2D_GPU(self.configs, parent=self)
292
293
 
293
294
 
@@ -1165,6 +1166,22 @@ class Config_Manager_2D_GPU:
1165
1166
  logging.error(_("No 'bathymetry.tif' file found in the root directory !"))
1166
1167
 
1167
1168
 
1169
+ def verify_bath_roof_deck(self, bathymetry:WolfArray, bridge_roof:WolfArray):
1170
+ """ Verify bathymetry, roof and deck """
1171
+
1172
+ if bridge_roof is None:
1173
+ return
1174
+
1175
+ # si la matrice de toit de pont est plus basse que la bathymétrie, on met à 99999
1176
+ # la bathymétrie et le toit de pont.
1177
+ # Ainsi, ces maille seront infranchissables.
1178
+ # Cale peut être utile pour discrétiser les piles dans les données du toit, plutôt que de les
1179
+ # laisser inclure dans un fichier bath_ séparé.
1180
+ mask = bridge_roof.array.data < bathymetry.array.data
1181
+ bridge_roof.array.data[mask] = 99999.
1182
+ bathymetry.array.data[mask] = 99999.
1183
+
1184
+
1168
1185
  def create_simulation(self,
1169
1186
  dir:Path,
1170
1187
  idx_hydros:list[int] = [-1],
@@ -1280,6 +1297,8 @@ class Config_Manager_2D_GPU:
1280
1297
  # applying Python scrpitps on ARRAYS
1281
1298
  self._apply_scripts_update_topo_maning_inf_roof(dir, bat, man, infiltration, roof)
1282
1299
 
1300
+ self.verify_bath_roof_deck(bat, roof)
1301
+
1283
1302
  # save arrays on disk
1284
1303
  bat.write_all(str(dir / '__bathymetry_after_scripts.tif'))
1285
1304
  man.write_all(str(dir / '__manning_after_scripts.tif'))
@@ -1398,12 +1417,12 @@ class Config_Manager_2D_GPU:
1398
1417
  f.write(str(curdir.drive) + '\n')
1399
1418
  f.write('cd {}\n'.format(str(curdir.parent)))
1400
1419
  f.write("\n")
1401
- f.write("WOLFGPU_PARAMS=-quickrun " + str(curdir.name) + "\n")
1420
+ f.write("set WOLFGPU_PARAMS=-quickrun " + str(curdir.name) + "\n")
1402
1421
  f.write("\n")
1403
1422
  f.write("where wolfgpu.exe\n")
1404
1423
  f.write("IF %ERRORLEVEL%==0 (\n")
1405
1424
  f.write("wolfgpu %WOLFGPU_PARAMS%\n")
1406
- f.write("goto :end\n")
1425
+ f.write("goto :exit\n")
1407
1426
  f.write(")\n")
1408
1427
  f.write("\n")
1409
1428
  f.write("echo -------------------------------\n")
@@ -1417,7 +1436,7 @@ class Config_Manager_2D_GPU:
1417
1436
  f.write("echo -------------------------------\n")
1418
1437
  f.write("pause\n")
1419
1438
  f.write("python -m wolfgpu.cli %WOLFGPU_PARAMS%\n")
1420
- f.write(":end\n")
1439
+ f.write(":exit\n")
1421
1440
 
1422
1441
  allsims.append(curdir / 'quickrun.bat')
1423
1442
 
@@ -2588,4 +2607,4 @@ class UI_Manager_2D_GPU():
2588
2607
  newroot = self._treelist.AppendItem(root, k, data = v)
2589
2608
 
2590
2609
  for curfile in v:
2591
- self._treelist.AppendItem(newroot, curfile.name, data = curfile)
2610
+ self._treelist.AppendItem(newroot, curfile.name, data = curfile)
wolfhece/wolf_array.py CHANGED
@@ -3335,9 +3335,16 @@ class SelectionData():
3335
3335
  else:
3336
3336
  destxy = self.myselection
3337
3337
 
3338
- destij = np.asarray([list(curarray.get_ij_from_xy(x, y)) for x, y in destxy])
3338
+ if len(destxy) == 0:
3339
+ logging.error(_('No selection to unmask'))
3340
+ return
3341
+
3342
+ if destxy == 'all':
3343
+ curarray.array.mask[:, :] = False
3344
+ else:
3345
+ destij = np.asarray([list(curarray.get_ij_from_xy(x, y)) for x, y in destxy])
3339
3346
 
3340
- curarray.array.mask[destij[:, 0], destij[:, 1]] = False
3347
+ curarray.array.mask[destij[:, 0], destij[:, 1]] = False
3341
3348
 
3342
3349
  if resetplot:
3343
3350
  curarray.reset_plot()
@@ -5629,7 +5636,7 @@ class WolfArray(Element_To_Draw, header_wolf):
5629
5636
  - Float32
5630
5637
  - Float64
5631
5638
 
5632
- :param outdir: directory - If provided, the file will be savd as "outdir/idx+extent.tif"
5639
+ :param outdir: directory - If provided, the file will be savd as "outdir/idx+extent.tif"
5633
5640
  If not provided, we use the filename attribute
5634
5641
 
5635
5642
  :param extent: suffix to add to the filename before the extension '.tif' (only if outdir is provided)
@@ -5749,7 +5756,7 @@ class WolfArray(Element_To_Draw, header_wolf):
5749
5756
  assert locarray.shape[1] == self.nby, _('Incompatible dimensions')
5750
5757
 
5751
5758
  if crop is not None :
5752
- logging.error(_('Cropping not yet implemented for numpy files'))
5759
+ # logging.error(_('Cropping not yet implemented for numpy files'))
5753
5760
 
5754
5761
  imin, jmin = self.get_ij_from_xy(crop[0][0], crop[1][0])
5755
5762
  imax, jmax = self.get_ij_from_xy(crop[0][1], crop[1][1])
@@ -5795,6 +5802,7 @@ class WolfArray(Element_To_Draw, header_wolf):
5795
5802
  else:
5796
5803
  return
5797
5804
 
5805
+ raster:gdal.Dataset
5798
5806
  if crop is not None :
5799
5807
  if not os.path.exists(fn):
5800
5808
  logging.error(_('File not found'))
@@ -5812,12 +5820,35 @@ class WolfArray(Element_To_Draw, header_wolf):
5812
5820
  logging.error(_('Crop must be a list or a numpy array with 4 values - xmin, xmax, ymin, ymax'))
5813
5821
  return
5814
5822
 
5815
- raster:gdal.Dataset
5816
- raster = gdal.Open(fn)
5817
- geotr = raster.GetGeoTransform()
5823
+ raster_in:gdal.Dataset
5824
+ raster_in = gdal.Open(fn)
5825
+
5826
+ proj = raster_in.GetProjection()
5827
+ # check if proj is epsg:31370
5828
+ if 'Lambert 72' not in proj and "31370" not in proj:
5829
+ logging.error(_('{} projection is not Lambert 72 - EPSG:31370').format(fn))
5830
+
5831
+ raster_in2 = gdal.Dataset()
5832
+ gdal.Warp(raster_in2, raster_in, dstSRS='EPSG:31370')
5833
+
5834
+ # Close the raster_in
5835
+ raster_in.FlushCache()
5836
+ raster_in = None
5837
+
5838
+ raster_in = raster_in2
5839
+
5840
+ if raster_in is None:
5841
+ logging.error(_('Could not reproject the file {fn}'))
5842
+ return
5843
+
5844
+ geotr = raster_in.GetGeoTransform()
5818
5845
  self.dx = geotr[1]
5819
5846
  self.dy = abs(geotr[5])
5820
5847
 
5848
+ ulx = geotr[0]
5849
+ uly = geotr[3]
5850
+ llx = ulx + geotr[1] * raster_in.RasterXSize
5851
+ lly = uly + geotr[5] * raster_in.RasterYSize
5821
5852
 
5822
5853
  newcrop = CropDialog(None)
5823
5854
 
@@ -5868,20 +5899,29 @@ class WolfArray(Element_To_Draw, header_wolf):
5868
5899
 
5869
5900
  fn_crop = fileDialog.GetPath()
5870
5901
 
5902
+ if uly > lly:
5903
+ raster = gdal.Translate(fn_crop, fn, projWin=[xmin, ymax, xmax, ymin])
5904
+ else:
5905
+ raster = gdal.Translate(fn_crop, fn, projWin=[xmin, ymin, xmax, ymax])
5871
5906
 
5872
- gdal.Translate(fn_crop, fn, projWin=[xmin, ymax, xmax, ymin])
5873
5907
  fn = fn_crop
5874
5908
  else:
5875
5909
  from tempfile import NamedTemporaryFile
5876
5910
  tmpfile = NamedTemporaryFile(suffix='.tif')
5877
- gdal.Translate(str(tmpfile.name), fn, projWin=[xmin, ymax, xmax, ymin])
5911
+
5912
+ if uly > lly:
5913
+ raster = gdal.Translate(str(tmpfile.name), fn, projWin=[xmin, ymax, xmax, ymin])
5914
+ else:
5915
+ raster = gdal.Translate(str(tmpfile.name), fn, projWin=[xmin, ymin, xmax, ymax])
5916
+
5878
5917
  fn = str(tmpfile.name)
5918
+ else:
5919
+ raster = gdal.Open(fn)
5879
5920
 
5880
- raster:gdal.Dataset
5881
- raster = gdal.Open(fn)
5882
5921
 
5883
- # Projection
5884
- # proj = raster.GetProjection()
5922
+ if raster is None:
5923
+ logging.error(_('Could not open the file {fn}'))
5924
+ return
5885
5925
 
5886
5926
  # Dimensions
5887
5927
  self.nbx = raster.RasterXSize
@@ -7936,41 +7976,51 @@ class WolfArray(Element_To_Draw, header_wolf):
7936
7976
  elif type(self.cropini) is list:
7937
7977
  pass
7938
7978
  else:
7939
- newcrop = CropDialog(None)
7979
+ if self.wx_exists:
7980
+ newcrop = CropDialog(None)
7940
7981
 
7941
- if self.mapviewer is not None:
7942
- bounds = self.mapviewer.get_canvas_bounds()
7982
+ if self.mapviewer is not None:
7983
+ bounds = self.mapviewer.get_canvas_bounds()
7943
7984
 
7944
- newcrop.dx.Value = str(self.dx)
7945
- newcrop.dy.Value = str(self.dy)
7985
+ newcrop.dx.Value = str(self.dx)
7986
+ newcrop.dy.Value = str(self.dy)
7946
7987
 
7947
- # newcrop.dx.Enable(False)
7948
- # newcrop.dy.Enable(False)
7988
+ # newcrop.dx.Enable(False)
7989
+ # newcrop.dy.Enable(False)
7949
7990
 
7950
- newcrop.ox.Value = str(float((bounds[0] // 50.) * 50.))
7951
- newcrop.ex.Value = str(float((bounds[2] // 50.) * 50.))
7952
- newcrop.oy.Value = str(float((bounds[1] // 50.) * 50.))
7953
- newcrop.ey.Value = str(float((bounds[3] // 50.) * 50.))
7991
+ newcrop.ox.Value = str(float((bounds[0] // 50.) * 50.))
7992
+ newcrop.ex.Value = str(float((bounds[2] // 50.) * 50.))
7993
+ newcrop.oy.Value = str(float((bounds[1] // 50.) * 50.))
7994
+ newcrop.ey.Value = str(float((bounds[3] // 50.) * 50.))
7954
7995
 
7955
- badvalues = True
7956
- while badvalues:
7957
- badvalues = False
7996
+ badvalues = True
7997
+ while badvalues:
7998
+ badvalues = False
7958
7999
 
7959
- ret = newcrop.ShowModal()
7960
- if ret == wx.ID_CANCEL:
7961
- newcrop.Destroy()
7962
- return
7963
- else:
7964
- self.cropini = [[float(newcrop.ox.Value), float(newcrop.ex.Value)],
7965
- [float(newcrop.oy.Value), float(newcrop.ey.Value)]]
7966
- tmpdx = float(newcrop.dx.Value)
7967
- tmpdy = float(newcrop.dy.Value)
8000
+ ret = newcrop.ShowModal()
8001
+ if ret == wx.ID_CANCEL:
8002
+ newcrop.Destroy()
8003
+ return
8004
+ else:
8005
+ self.cropini = [[float(newcrop.ox.Value), float(newcrop.ex.Value)],
8006
+ [float(newcrop.oy.Value), float(newcrop.ey.Value)]]
8007
+ tmpdx = float(newcrop.dx.Value)
8008
+ tmpdy = float(newcrop.dy.Value)
8009
+
8010
+ if self.dx != tmpdx or self.dy != tmpdy:
8011
+ if tmpdx / self.dx != tmpdy / self.dy:
8012
+ badvalues = True
8013
+
8014
+ newcrop.Destroy()
8015
+
8016
+ self.cropini = [[self.cropini[0][0] + self.dx/2., self.cropini[0][1] + self.dx/2.],
8017
+ [self.cropini[1][0] + self.dy/2., self.cropini[1][1] + self.dy/2.]]
8018
+ else:
8019
+ logging.warning(_('No crop defined and no wxPython available'))
8020
+ logging.info(_('Abort reading data !'))
8021
+ return
7968
8022
 
7969
- if self.dx != tmpdx or self.dy != tmpdy:
7970
- if tmpdx / self.dx != tmpdy / self.dy:
7971
- badvalues = True
7972
8023
 
7973
- newcrop.Destroy()
7974
8024
 
7975
8025
  with open(self.filename, 'rb') as f:
7976
8026
  if self.wolftype == WOLF_ARRAY_FULL_SINGLE or self.wolftype == WOLF_ARRAY_FULL_SINGLE_3D:
@@ -8007,6 +8057,10 @@ class WolfArray(Element_To_Draw, header_wolf):
8007
8057
 
8008
8058
  self.array = ma.masked_array(locarray, dtype=np.float32)
8009
8059
 
8060
+ else:
8061
+ logging.warning(_('Unsupported wolftype for cropping'))
8062
+ return
8063
+
8010
8064
  if self.filename.endswith('.flt'):
8011
8065
  # fichier .flt --> miroir "horizontal"
8012
8066
  self.array = np.fliplr(self.array)