wolfhece 2.1.46__py3-none-any.whl → 2.1.49__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/Coordinates_operations.py +189 -0
- wolfhece/PyDraw.py +2 -0
- wolfhece/PyVertexvectors.py +94 -15
- wolfhece/apps/version.py +1 -1
- wolfhece/drawing_obj.py +8 -1
- wolfhece/wolf_array.py +275 -33
- {wolfhece-2.1.46.dist-info → wolfhece-2.1.49.dist-info}/METADATA +8 -8
- {wolfhece-2.1.46.dist-info → wolfhece-2.1.49.dist-info}/RECORD +11 -10
- {wolfhece-2.1.46.dist-info → wolfhece-2.1.49.dist-info}/WHEEL +0 -0
- {wolfhece-2.1.46.dist-info → wolfhece-2.1.49.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.1.46.dist-info → wolfhece-2.1.49.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,189 @@
|
|
1
|
+
from pyproj import Transformer
|
2
|
+
from concurrent.futures import ProcessPoolExecutor
|
3
|
+
import numpy as np
|
4
|
+
from osgeo import gdal
|
5
|
+
import os
|
6
|
+
import logging
|
7
|
+
|
8
|
+
from .PyTranslate import _
|
9
|
+
|
10
|
+
def transform_chunk_coordinates(inputEPSG:str, outputEPSG:str, chunk:np.ndarray):
|
11
|
+
"""
|
12
|
+
Transforms a chunk of coordinates
|
13
|
+
|
14
|
+
:param inputEPSG: input EPSG code (e.g. "EPSG:3812")
|
15
|
+
:type inputEPSG: str
|
16
|
+
:param outputEPSG: output EPSG code (e.g. "EPSG:31370")
|
17
|
+
:type outputEPSG: str
|
18
|
+
:param chunk: list of points to be transformed
|
19
|
+
:type chunk: np.ndarray
|
20
|
+
"""
|
21
|
+
COO_TRANSFORMER = Transformer.from_crs(inputEPSG, outputEPSG, always_xy=True)
|
22
|
+
return COO_TRANSFORMER.transform(chunk[:, 0], chunk[:, 1])
|
23
|
+
|
24
|
+
def transform_coordinates(points:np.ndarray, inputEPSG:str="EPSG:3812", outputEPSG:str="EPSG:31370", chunk_size:int=1000):
|
25
|
+
"""
|
26
|
+
Transforms coordinates in batches using multiprocessing. If more than chunk_size points are provided, the
|
27
|
+
function will split the points into chunks and transform them in parallel => requiring in the main script
|
28
|
+
to use the statement if __name__ == '__main__':.
|
29
|
+
|
30
|
+
:param points: Array of coordinates to be transformed
|
31
|
+
:type points: numpy.ndarray
|
32
|
+
:param inputEPSG: (optional) Input EPSG code. Defaults to "EPSG:3812"
|
33
|
+
:type inputEPSG: str
|
34
|
+
:param outputEPSG: (optional) Output EPSG code. Defaults to "EPSG:31370"
|
35
|
+
:type outputEPSG: str
|
36
|
+
:param chunk_size: (optional) Size of each batch for transformation. Defaults to 100000
|
37
|
+
:type chunk_size: int
|
38
|
+
|
39
|
+
:return numpy.ndarray: Transformed coordinates
|
40
|
+
"""
|
41
|
+
|
42
|
+
# sanitize inputs
|
43
|
+
inputEPSG = str(inputEPSG)
|
44
|
+
outputEPSG = str(outputEPSG)
|
45
|
+
|
46
|
+
if not "EPSG" in inputEPSG or not "EPSG" in inputEPSG:
|
47
|
+
logging.error(_("EPSG code must be in the format 'EPSG:XXXX'"))
|
48
|
+
return
|
49
|
+
|
50
|
+
num_points = len(points)
|
51
|
+
results = []
|
52
|
+
|
53
|
+
total_steps = (num_points + chunk_size - 1) // chunk_size
|
54
|
+
|
55
|
+
if total_steps == 1:
|
56
|
+
result_x, result_y = transform_chunk_coordinates(inputEPSG, outputEPSG, points)
|
57
|
+
return np.vstack((result_x, result_y)).T
|
58
|
+
|
59
|
+
with ProcessPoolExecutor() as executor:
|
60
|
+
futures = []
|
61
|
+
for i in range(0, num_points, chunk_size):
|
62
|
+
chunk = points[i:i + chunk_size]
|
63
|
+
futures.append(executor.submit(transform_chunk_coordinates, inputEPSG, outputEPSG, chunk))
|
64
|
+
|
65
|
+
for step, future in enumerate(futures):
|
66
|
+
result_x, result_y = future.result()
|
67
|
+
results.append(np.vstack((result_x, result_y)).T)
|
68
|
+
|
69
|
+
return np.vstack(results)
|
70
|
+
|
71
|
+
def reproject_and_resample_raster(input_raster_path:str, output_raster_path:str,
|
72
|
+
input_srs:str='EPSG:3812', output_srs:str='EPSG:31370',
|
73
|
+
resampling_method:str|int=gdal.GRA_Bilinear,
|
74
|
+
xRes:float=0.5, yRes:float=0.5, debug:bool=False):
|
75
|
+
"""
|
76
|
+
Use gdal to open a tiff raster in a given input EPSG 'inputEPSG' and transforms the raster into another EPSG system 'outputEPSG'.
|
77
|
+
The resolution can be forced through xRes and yRes (the origin will be rounded to the nearest multiple of the resolution). The
|
78
|
+
resampling method can be chosen among the gdal GRA_* constants (gdal.GRA_Average; gdal.GRA_Bilinear; gdal.GRA_Cubic; gdal.GRA_CubicSpline;
|
79
|
+
gdal.GRA_Lanczos; gdal.GRA_Mode; gdal.GRA_NearestNeighbor).
|
80
|
+
|
81
|
+
:param input_raster_path: the path to the input raster file (.tif or .tiff)
|
82
|
+
:type input_raster_path: str
|
83
|
+
:param output_raster_path: the path to the output raster file (.tif or .tiff) that will be created
|
84
|
+
:type output_raster_path: str
|
85
|
+
:param input_srs: Input EPSG code. Defaults to Lambert 2008 "EPSG:3812"
|
86
|
+
:type input_srs: str
|
87
|
+
:param output_srs: Output EPSG code. Defaults to Lambert 72 "EPSG:31370"
|
88
|
+
:type output_srs: str
|
89
|
+
:param resampling_method: Resampling method. Defaults to gdal.GRA_Bilinear
|
90
|
+
:type resampling_method: int, str
|
91
|
+
:param xRes: Resolution along X. Defaults to 0.5
|
92
|
+
:type xRes: float
|
93
|
+
:param yRes: Resolution along Y. Defaults to 0.5
|
94
|
+
:type yRes: float
|
95
|
+
:param debug: If True, print debug information. Defaults to False
|
96
|
+
:type debug: bool
|
97
|
+
"""
|
98
|
+
from osgeo import osr
|
99
|
+
|
100
|
+
# santitize inputs
|
101
|
+
input_raster_path = str(input_raster_path)
|
102
|
+
output_raster_path = str(output_raster_path)
|
103
|
+
|
104
|
+
# ATTENTION: mask values should be negative in the tiff corresponding to input_raster_path!
|
105
|
+
if not(input_raster_path.endswith('.tif') or input_raster_path.endswith('.tiff')):
|
106
|
+
logging.error(_("Input raster must be a GeoTIFF file"))
|
107
|
+
return
|
108
|
+
if not(output_raster_path.endswith('.tif') or output_raster_path.endswith('.tiff')):
|
109
|
+
logging.error(_("Output raster must be a GeoTIFF file"))
|
110
|
+
return
|
111
|
+
|
112
|
+
# check the output file
|
113
|
+
if os.path.exists(output_raster_path):
|
114
|
+
try:
|
115
|
+
os.remove(output_raster_path)
|
116
|
+
except PermissionError as e:
|
117
|
+
logging.error(_(f"Permission denied while trying to delete {output_raster_path}. Ensure the file is not open in another program and you have sufficient privileges."))
|
118
|
+
return
|
119
|
+
except Exception as e:
|
120
|
+
logging.error(_(f"An unexpected error occurred while trying to delete {output_raster_path}: {str(e)}"))
|
121
|
+
return
|
122
|
+
|
123
|
+
# Open the input raster
|
124
|
+
input_raster = gdal.Open(input_raster_path)
|
125
|
+
if input_raster is None:
|
126
|
+
logging.error(_(f"Unable to open input raster: {input_raster_path}"))
|
127
|
+
return
|
128
|
+
|
129
|
+
# Get the source SRS from the input raster
|
130
|
+
source_srs = osr.SpatialReference()
|
131
|
+
if debug:
|
132
|
+
print('Initial projection: ',input_raster.GetProjection())
|
133
|
+
print('set projection init: ',int(input_srs.split(':')[1]))
|
134
|
+
source_srs.ImportFromEPSG(int(input_srs.split(':')[1]))
|
135
|
+
|
136
|
+
# Create the target SRS
|
137
|
+
target_srs = osr.SpatialReference()
|
138
|
+
if debug:
|
139
|
+
print('set projection out: ',int(output_srs.split(':')[1]))
|
140
|
+
target_srs.ImportFromEPSG(int(output_srs.split(':')[1]))
|
141
|
+
|
142
|
+
# Define the options for the reprojection
|
143
|
+
# Load the initial array to obtain the origin and the limits
|
144
|
+
ulx, xres, xskew, uly, yskew, yres = input_raster.GetGeoTransform()
|
145
|
+
Orig = np.array([[ulx,uly],
|
146
|
+
[ulx+input_raster.RasterXSize*xres, uly+input_raster.RasterYSize*yres]])
|
147
|
+
Orig.sort(0)
|
148
|
+
|
149
|
+
# Transform the origin and the limits into the new projection 'Lambert 72'
|
150
|
+
Orig_out = transform_coordinates(Orig, inputEPSG=input_srs, outputEPSG=output_srs)
|
151
|
+
|
152
|
+
# Round each coordinate to the nearest multiple of the wanted resolution
|
153
|
+
Orig_out[:,0] = np.round(Orig_out[:,0]/xRes)*xRes
|
154
|
+
Orig_out[:,1] = np.round(Orig_out[:,1]/yRes)*yRes
|
155
|
+
if debug:
|
156
|
+
print(Orig_out)
|
157
|
+
print(tuple(Orig_out.reshape(-1)))
|
158
|
+
|
159
|
+
# Define the reprojection options
|
160
|
+
# outputBounds=tuple(Orig_out.reshape(-1)),
|
161
|
+
# xRes=xRes, yRes=yRes,
|
162
|
+
reproject_options = gdal.WarpOptions(
|
163
|
+
outputBounds=tuple(Orig_out.reshape(-1)), # Output bounds: (minX, minY, maxX, maxY)
|
164
|
+
xRes=xRes, yRes=yRes,
|
165
|
+
srcSRS=source_srs.ExportToWkt(),
|
166
|
+
dstSRS=target_srs.ExportToWkt(),
|
167
|
+
resampleAlg=resampling_method
|
168
|
+
)
|
169
|
+
|
170
|
+
# Reproject and resample the input raster
|
171
|
+
output_raster = gdal.Warp(
|
172
|
+
destNameOrDestDS=output_raster_path,
|
173
|
+
srcDSOrSrcDSTab=input_raster,
|
174
|
+
options=reproject_options
|
175
|
+
)
|
176
|
+
|
177
|
+
if output_raster is None:
|
178
|
+
logging.error(_(f"Reprojection failed for input raster: {input_raster_path}"))
|
179
|
+
return
|
180
|
+
|
181
|
+
# Flush cache to ensure the output is written to disk
|
182
|
+
output_raster.FlushCache()
|
183
|
+
|
184
|
+
# Close the datasets IMPORTANT to set to None in order to close them
|
185
|
+
input_raster = None
|
186
|
+
output_raster = None
|
187
|
+
|
188
|
+
if debug:
|
189
|
+
print(f"Reprojection and resampling completed successfully. Output saved to: {output_raster_path}")
|
wolfhece/PyDraw.py
CHANGED
wolfhece/PyVertexvectors.py
CHANGED
@@ -885,6 +885,21 @@ if :\n \
|
|
885
885
|
self.myprops.SetSizeHints(500,800)
|
886
886
|
self.myprops.Show()
|
887
887
|
|
888
|
+
self.myprops.SetTitle(_('Vector properties - {}'.format(self.parent.myname)))
|
889
|
+
self.myprops.Center()
|
890
|
+
self.myprops.Raise()
|
891
|
+
|
892
|
+
def show_properties(self):
|
893
|
+
""" Show the properties -- alias of show() """
|
894
|
+
|
895
|
+
self.show()
|
896
|
+
|
897
|
+
def hide_properties(self):
|
898
|
+
""" Hide the properties """
|
899
|
+
|
900
|
+
if self.myprops is not None:
|
901
|
+
self.myprops.Hide()
|
902
|
+
|
888
903
|
def _convert_fontname2int(self, fontname:str) -> int:
|
889
904
|
|
890
905
|
if fontname.lower() in 'arial.ttf':
|
@@ -1002,6 +1017,18 @@ class vector:
|
|
1002
1017
|
if fromshapely is not None:
|
1003
1018
|
self.import_shapelyobj(fromshapely)
|
1004
1019
|
|
1020
|
+
def show_properties(self):
|
1021
|
+
""" Show the properties """
|
1022
|
+
|
1023
|
+
if self.myprop is not None:
|
1024
|
+
self.myprop.show()
|
1025
|
+
|
1026
|
+
def hide_properties(self):
|
1027
|
+
""" Hide the properties """
|
1028
|
+
|
1029
|
+
if self.myprop is not None:
|
1030
|
+
self.myprop.hide_properties()
|
1031
|
+
|
1005
1032
|
def get_mapviewer(self):
|
1006
1033
|
""" Return the mapviewer """
|
1007
1034
|
|
@@ -1652,7 +1679,7 @@ class vector:
|
|
1652
1679
|
logging.warning(_('No mapviewer available for legend plot'))
|
1653
1680
|
return
|
1654
1681
|
|
1655
|
-
if self.myprop.legendvisible:
|
1682
|
+
if self.myprop.legendvisible and self.myprop.used:
|
1656
1683
|
|
1657
1684
|
self.textimage = Text_Image_Texture(self.myprop.legendtext,
|
1658
1685
|
self.get_mapviewer(), # mapviewer de l'instance Zones qui contient le vecteur
|
@@ -1671,7 +1698,7 @@ class vector:
|
|
1671
1698
|
logging.warning(_('No mapviewer available for image plot'))
|
1672
1699
|
return
|
1673
1700
|
|
1674
|
-
if self.myprop.imagevisible:
|
1701
|
+
if self.myprop.imagevisible and self.myprop.used:
|
1675
1702
|
|
1676
1703
|
if self.myprop.textureimage is None:
|
1677
1704
|
self.myprop.load_unload_image()
|
@@ -2325,7 +2352,9 @@ class zone:
|
|
2325
2352
|
is2D:bool=True,
|
2326
2353
|
fromshapely:Union[LineString,Polygon,MultiLineString, MultiPolygon]=None) -> None:
|
2327
2354
|
|
2355
|
+
self.myprop = None
|
2328
2356
|
self.myprops = None
|
2357
|
+
|
2329
2358
|
self.myname = '' # name of the zone
|
2330
2359
|
self.idgllist = -99999 # id of the zone in the gllist
|
2331
2360
|
self.active_vector=None # current active vector
|
@@ -3526,6 +3555,7 @@ class zone:
|
|
3526
3555
|
"""
|
3527
3556
|
Compute statistics on values dict resulting from 'get_values_linked_polygons'
|
3528
3557
|
"""
|
3558
|
+
|
3529
3559
|
for curpol in vals.values():
|
3530
3560
|
medianlist =curpol['median'] = []
|
3531
3561
|
meanlist = curpol['mean'] = []
|
@@ -3570,7 +3600,10 @@ class zone:
|
|
3570
3600
|
p95.append(None)
|
3571
3601
|
p5.append(None)
|
3572
3602
|
|
3573
|
-
def plot_linked_polygons(self, fig:Figure, ax:Axes,
|
3603
|
+
def plot_linked_polygons(self, fig:Figure, ax:Axes,
|
3604
|
+
linked_arrays:dict, linked_vec:dict[str,"Zones"]=None,
|
3605
|
+
linestyle:str='-', onlymedian:bool=False,
|
3606
|
+
withtopography:bool = True, ds:float = None):
|
3574
3607
|
"""
|
3575
3608
|
Création d'un graphique sur base des polygones
|
3576
3609
|
|
@@ -3591,6 +3624,7 @@ class zone:
|
|
3591
3624
|
:param ds: pas spatial le long de l'axe
|
3592
3625
|
|
3593
3626
|
"""
|
3627
|
+
|
3594
3628
|
colors=['red','blue','green','darkviolet','fuchsia','lime']
|
3595
3629
|
|
3596
3630
|
#Vérifie qu'au moins une matrice liée est fournie, sinon rien à faire
|
@@ -3790,16 +3824,19 @@ class zone:
|
|
3790
3824
|
|
3791
3825
|
def reset_listogl(self):
|
3792
3826
|
"""
|
3793
|
-
Reset
|
3827
|
+
Reset OpenGL lists.
|
3828
|
+
|
3829
|
+
Force deletion of the OpenGL list.
|
3830
|
+
If the object is newly plotted, the lists will be recreated.
|
3794
3831
|
"""
|
3832
|
+
|
3795
3833
|
if self.idgllist!=-99999:
|
3796
3834
|
glDeleteLists(self.idgllist,1)
|
3797
3835
|
self.idgllist=-99999
|
3798
3836
|
|
3799
3837
|
def deepcopy_zone(self, name: str =None, parent: str= None):
|
3800
|
-
"""
|
3801
|
-
|
3802
|
-
"""
|
3838
|
+
""" Return a deep copy of the zone"""
|
3839
|
+
|
3803
3840
|
if name is None:
|
3804
3841
|
name = self.myname + '_copy'
|
3805
3842
|
if parent:
|
@@ -3817,9 +3854,10 @@ class zone:
|
|
3817
3854
|
def show_properties(self):
|
3818
3855
|
""" Show properties of the zone --> will be applied to all vectors int he zone """
|
3819
3856
|
|
3820
|
-
|
3821
|
-
|
3822
|
-
|
3857
|
+
if self.myprops is None:
|
3858
|
+
locvec = vector()
|
3859
|
+
locvec.show_properties()
|
3860
|
+
self.myprops = locvec.myprop.myprops
|
3823
3861
|
|
3824
3862
|
self.myprops[('Legend','X')] = 99999.
|
3825
3863
|
self.myprops[('Legend','Y')] = 99999.
|
@@ -3827,11 +3865,31 @@ class zone:
|
|
3827
3865
|
self.myprops.Populate()
|
3828
3866
|
self.myprops.set_callbacks(self._callback_prop, self._callback_destroy_props)
|
3829
3867
|
|
3868
|
+
self.myprops.SetTitle(_('Zone properties - {}'.format(self.myname)))
|
3869
|
+
self.myprops.Center()
|
3870
|
+
self.myprops.Raise()
|
3871
|
+
|
3872
|
+
def hide_properties(self):
|
3873
|
+
""" Hide the properties window """
|
3874
|
+
|
3875
|
+
if self.myprops is not None:
|
3876
|
+
# window for general properties
|
3877
|
+
self.myprops.Hide()
|
3878
|
+
|
3879
|
+
for curvect in self.myvectors:
|
3880
|
+
curvect.hide_properties()
|
3881
|
+
|
3882
|
+
|
3830
3883
|
def _callback_destroy_props(self):
|
3884
|
+
""" Callback to destroy the properties window """
|
3885
|
+
|
3886
|
+
if self.myprops is not None:
|
3887
|
+
self.myprops.Destroy()
|
3831
3888
|
|
3832
3889
|
self.myprops = None
|
3833
3890
|
|
3834
3891
|
def _callback_prop(self):
|
3892
|
+
""" Callback to update properties """
|
3835
3893
|
|
3836
3894
|
if self.myprops is None:
|
3837
3895
|
logging.warning(_('No properties available'))
|
@@ -3848,6 +3906,7 @@ class zone:
|
|
3848
3906
|
"""
|
3849
3907
|
Set the legend to the centroid of the zone
|
3850
3908
|
"""
|
3909
|
+
|
3851
3910
|
for curvec in self.myvectors:
|
3852
3911
|
curvec.set_legend_to_centroid()
|
3853
3912
|
|
@@ -3914,6 +3973,8 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
3914
3973
|
|
3915
3974
|
Element_To_Draw.__init__(self, idx, plotted, mapviewer, need_for_wx)
|
3916
3975
|
|
3976
|
+
self._myprops = None # common properties of all zones
|
3977
|
+
|
3917
3978
|
self.loaded=True
|
3918
3979
|
|
3919
3980
|
self.active_vector:vector = None
|
@@ -4521,7 +4582,18 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
4521
4582
|
si parent est d'un autre type, il faut s'assurer que les options/actions sont consistantes
|
4522
4583
|
|
4523
4584
|
"""
|
4524
|
-
self.showstructure(parent,forceupdate)
|
4585
|
+
self.showstructure(parent, forceupdate)
|
4586
|
+
|
4587
|
+
def hide_properties(self):
|
4588
|
+
""" Hide the properties window """
|
4589
|
+
|
4590
|
+
self.Hide()
|
4591
|
+
|
4592
|
+
if self._myprops is not None:
|
4593
|
+
self._myprops.Hide()
|
4594
|
+
|
4595
|
+
for curzone in self.myzones:
|
4596
|
+
curzone.hide_properties()
|
4525
4597
|
|
4526
4598
|
def showstructure(self, parent=None, forceupdate=False):
|
4527
4599
|
"""
|
@@ -4547,6 +4619,8 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
4547
4619
|
self.init_ui()
|
4548
4620
|
|
4549
4621
|
self.Show()
|
4622
|
+
self.Center()
|
4623
|
+
self.Raise()
|
4550
4624
|
|
4551
4625
|
def init_ui(self):
|
4552
4626
|
"""
|
@@ -6056,10 +6130,11 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
6056
6130
|
def _edit_all_properties(self):
|
6057
6131
|
""" Show properties of the zone --> will be applied to all vectors int he zone """
|
6058
6132
|
|
6059
|
-
|
6060
|
-
|
6133
|
+
if self._myprops is None:
|
6134
|
+
locvec = vector()
|
6135
|
+
locvec.show_properties()
|
6061
6136
|
|
6062
|
-
|
6137
|
+
self._myprops = locvec.myprop.myprops
|
6063
6138
|
|
6064
6139
|
self._myprops[('Legend','X')] = 99999.
|
6065
6140
|
self._myprops[('Legend','Y')] = 99999.
|
@@ -6067,6 +6142,10 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
6067
6142
|
self._myprops.Populate()
|
6068
6143
|
self._myprops.set_callbacks(self._callback_prop, self._callback_destroy_props)
|
6069
6144
|
|
6145
|
+
self._myprops.SetTitle(_('Properties for all vectors in {}'.format(self.myname)))
|
6146
|
+
self._myprops.Center()
|
6147
|
+
self._myprops.Raise()
|
6148
|
+
|
6070
6149
|
|
6071
6150
|
def OnRDown(self, event:TreeListEvent):
|
6072
6151
|
"""
|
@@ -6080,7 +6159,7 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
6080
6159
|
self._edit_all_properties()
|
6081
6160
|
|
6082
6161
|
elif isinstance(self.last_active, vector):
|
6083
|
-
self.active_vector.
|
6162
|
+
self.active_vector.show_properties()
|
6084
6163
|
|
6085
6164
|
elif isinstance(self.last_active, zone):
|
6086
6165
|
self.active_zone.show_properties()
|
wolfhece/apps/version.py
CHANGED
wolfhece/drawing_obj.py
CHANGED
@@ -92,6 +92,13 @@ class Element_To_Draw:
|
|
92
92
|
logging.warning('No properties to show for this object !')
|
93
93
|
pass
|
94
94
|
|
95
|
+
def hide_properties(self):
|
96
|
+
"""
|
97
|
+
Generic function to hide properties of the object
|
98
|
+
"""
|
99
|
+
logging.warning('No properties to hide for this object !')
|
100
|
+
pass
|
101
|
+
|
95
102
|
def plot(self, sx=None, sy=None, xmin=None, ymin=None, xmax=None, ymax=None, size=None):
|
96
103
|
"""
|
97
104
|
Plot data in OpenGL context
|
@@ -126,5 +133,5 @@ class Element_To_Draw:
|
|
126
133
|
"""
|
127
134
|
if self.mapviewer is None:
|
128
135
|
return False
|
129
|
-
|
136
|
+
|
130
137
|
return self.mapviewer.SetCurrentContext()
|
wolfhece/wolf_array.py
CHANGED
@@ -20,6 +20,7 @@ import numpy.ma as ma
|
|
20
20
|
import math as m
|
21
21
|
import logging
|
22
22
|
import json
|
23
|
+
import tempfile
|
23
24
|
from pathlib import Path
|
24
25
|
|
25
26
|
try:
|
@@ -45,7 +46,11 @@ from os.path import dirname,basename,join
|
|
45
46
|
import logging
|
46
47
|
from typing import Literal
|
47
48
|
from copy import deepcopy
|
49
|
+
from osgeo import gdal
|
50
|
+
from enum import Enum
|
48
51
|
|
52
|
+
|
53
|
+
from .Coordinates_operations import reproject_and_resample_raster
|
49
54
|
from .PyTranslate import _
|
50
55
|
from .GraphNotebook import PlotPanel
|
51
56
|
from .CpGrid import CpGrid
|
@@ -90,6 +95,42 @@ WOLF_ARRAY_MB = [WOLF_ARRAY_MB_SINGLE, WOLF_ARRAY_MB_INTEGER, WOLF_ARRAY_MNAP_IN
|
|
90
95
|
|
91
96
|
VERSION_RGB = 2
|
92
97
|
|
98
|
+
class Rebin_Ops(Enum):
|
99
|
+
MIN = 0
|
100
|
+
MEAN = 1
|
101
|
+
MAX = 2
|
102
|
+
SUM = 3
|
103
|
+
MEDIAN = 4
|
104
|
+
|
105
|
+
@classmethod
|
106
|
+
def get_numpy_ops(cls):
|
107
|
+
""" Return a list of numpy functions corresponding to the enum values """
|
108
|
+
|
109
|
+
# CAUTION : Order is important and must match the enum values
|
110
|
+
return [np.ma.min, np.ma.mean, np.ma.max, np.ma.sum, np.ma.median]
|
111
|
+
|
112
|
+
@classmethod
|
113
|
+
def get_ops(cls, name:str):
|
114
|
+
""" Return the numpy function corresponding to a string """
|
115
|
+
|
116
|
+
if isinstance(name, Rebin_Ops):
|
117
|
+
return cls.get_numpy_ops()[name.value]
|
118
|
+
elif isinstance(name, str):
|
119
|
+
if name == 'min':
|
120
|
+
return np.ma.min
|
121
|
+
elif name == 'mean':
|
122
|
+
return np.ma.mean
|
123
|
+
elif name == 'max':
|
124
|
+
return np.ma.max
|
125
|
+
elif name == 'sum':
|
126
|
+
return np.ma.sum
|
127
|
+
elif name == 'median':
|
128
|
+
return np.ma.median
|
129
|
+
else:
|
130
|
+
return None
|
131
|
+
else:
|
132
|
+
return None
|
133
|
+
|
93
134
|
def getkeyblock(i, addone=True) -> str:
|
94
135
|
"""
|
95
136
|
Name/Key of a block in the dictionnary of a WolfArrayMB instance
|
@@ -111,6 +152,9 @@ def decodekeyblock(key, addone=True) -> int:
|
|
111
152
|
return int(key[5:])
|
112
153
|
else:
|
113
154
|
return int(key[5:]) - 1
|
155
|
+
|
156
|
+
|
157
|
+
|
114
158
|
class header_wolf():
|
115
159
|
"""
|
116
160
|
Header of WolfArray
|
@@ -284,9 +328,9 @@ class header_wolf():
|
|
284
328
|
"""
|
285
329
|
Set translation
|
286
330
|
|
287
|
-
:param tr_x
|
288
|
-
:param tr_y
|
289
|
-
:param tr_z
|
331
|
+
:param tr_x: translation along X
|
332
|
+
:param tr_y: translation along Y
|
333
|
+
:param tr_z: translation along Z
|
290
334
|
"""
|
291
335
|
self.translx = tr_x
|
292
336
|
self.transly = tr_y
|
@@ -2277,6 +2321,15 @@ class Ops_Array(wx.Frame):
|
|
2277
2321
|
|
2278
2322
|
self.myzones.showstructure()
|
2279
2323
|
|
2324
|
+
def hide_properties(self):
|
2325
|
+
""" Hide the properties panel """
|
2326
|
+
|
2327
|
+
try:
|
2328
|
+
self.myzones.hide_properties()
|
2329
|
+
self.Hide()
|
2330
|
+
except Exception as e:
|
2331
|
+
logging.error('Error in hide_properties : %s' % e)
|
2332
|
+
|
2280
2333
|
def OnLoadvec(self, event:wx.MouseEvent):
|
2281
2334
|
""" Load vector file """
|
2282
2335
|
|
@@ -4396,14 +4449,24 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4396
4449
|
|
4397
4450
|
def __del__(self):
|
4398
4451
|
""" Destructeur de la classe """
|
4399
|
-
|
4400
|
-
|
4401
|
-
|
4402
|
-
|
4403
|
-
|
4404
|
-
|
4405
|
-
|
4406
|
-
|
4452
|
+
try:
|
4453
|
+
# Perform cleanup tasks safely
|
4454
|
+
self.delete_lists()
|
4455
|
+
if hasattr(self, 'array'):
|
4456
|
+
del self.array
|
4457
|
+
if VERSION_RGB == 1 and hasattr(self, 'rgb'):
|
4458
|
+
del self.rgb
|
4459
|
+
if hasattr(self, '_array3d'):
|
4460
|
+
del self._array3d
|
4461
|
+
if hasattr(self, 'mypal'):
|
4462
|
+
del self.mypal
|
4463
|
+
if hasattr(self, 'shaded'):
|
4464
|
+
del self.shaded
|
4465
|
+
# Perform garbage collection if gc is available
|
4466
|
+
import gc
|
4467
|
+
gc.collect()
|
4468
|
+
except Exception as e:
|
4469
|
+
print(f"Exception in WolfArray destructor: {e} -- Please report this issue")
|
4407
4470
|
|
4408
4471
|
def extract_selection(self):
|
4409
4472
|
""" Extract the current selection """
|
@@ -4491,6 +4554,15 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4491
4554
|
self.myops.SetTitle(_('Operations on array: ') + self.idx)
|
4492
4555
|
self.myops.Show()
|
4493
4556
|
|
4557
|
+
self.myops.Center()
|
4558
|
+
self.myops.Raise()
|
4559
|
+
|
4560
|
+
def hide_properties(self):
|
4561
|
+
""" Hide the properties window """
|
4562
|
+
|
4563
|
+
if self.wx_exists and self.myops is not None:
|
4564
|
+
self.myops.hide_properties()
|
4565
|
+
|
4494
4566
|
@property
|
4495
4567
|
def nullvalue(self) -> float:
|
4496
4568
|
""" Return the null value """
|
@@ -4802,7 +4874,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4802
4874
|
if reset_plot:
|
4803
4875
|
self.reset_plot()
|
4804
4876
|
|
4805
|
-
def export_geotif(self, outdir='', extent = ''):
|
4877
|
+
def export_geotif(self, outdir='', extent = '', EPSG:int = 31370):
|
4806
4878
|
"""
|
4807
4879
|
Export de la matrice au format Geotiff (Lambert 72 - EPSG:31370)
|
4808
4880
|
|
@@ -4813,11 +4885,12 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4813
4885
|
|
4814
4886
|
:param outdir: directory
|
4815
4887
|
:param extent: suffix to add to the filename before the extension '.tif'
|
4888
|
+
:param EPSG: EPSG code, by default 31370 (Lambert 72)
|
4816
4889
|
"""
|
4817
4890
|
from osgeo import gdal, osr, gdalconst
|
4818
4891
|
|
4819
4892
|
srs = osr.SpatialReference()
|
4820
|
-
srs.ImportFromEPSG(
|
4893
|
+
srs.ImportFromEPSG(EPSG)
|
4821
4894
|
|
4822
4895
|
if outdir=='' and extent=='':
|
4823
4896
|
filename = self.filename
|
@@ -4845,7 +4918,17 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4845
4918
|
out_ds: gdal.Dataset
|
4846
4919
|
band: gdal.Band
|
4847
4920
|
driver = gdal.GetDriverByName("GTiff")
|
4848
|
-
|
4921
|
+
# bytes_per_pixel = arr.data.dtype.itemsize
|
4922
|
+
estimated_file_size = self.memory_usage #arr.shape[0] * arr.shape[1] * bytes_per_pixel
|
4923
|
+
|
4924
|
+
# Check if estimated file size exceeds 4GB
|
4925
|
+
if (estimated_file_size > 4 * 1024**3): # 4GB in bytes
|
4926
|
+
options = ['COMPRESS=LZW', 'BIGTIFF=YES']
|
4927
|
+
print('BigTIFF format will be used!')
|
4928
|
+
else:
|
4929
|
+
options = ['COMPRESS=LZW']
|
4930
|
+
|
4931
|
+
out_ds = driver.Create(filename, arr.shape[0], arr.shape[1], 1, arr_type, options=options)
|
4849
4932
|
out_ds.SetProjection(srs.ExportToWkt())
|
4850
4933
|
|
4851
4934
|
|
@@ -5109,6 +5192,10 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
5109
5192
|
except:
|
5110
5193
|
logging.warning(_('Error during importing tif file'))
|
5111
5194
|
|
5195
|
+
# Close the raster
|
5196
|
+
raster.FlushCache()
|
5197
|
+
raster = None
|
5198
|
+
|
5112
5199
|
def add_ops_sel(self):
|
5113
5200
|
"""
|
5114
5201
|
Adding selection manager and operations array
|
@@ -6682,11 +6769,12 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
6682
6769
|
if update_min_max:
|
6683
6770
|
self.mypal.distribute_values(self.array.min(), self.array.max())
|
6684
6771
|
|
6685
|
-
def write_all(self, newpath:str = None):
|
6772
|
+
def write_all(self, newpath:str = None, EPSG:int = 31370):
|
6686
6773
|
"""
|
6687
6774
|
Ecriture de tous les fichiers d'un Wolf array
|
6688
6775
|
|
6689
6776
|
:param newpath: new path and filename with extension -- if None, use the current filename
|
6777
|
+
:param EPSG: EPSG code for geotiff
|
6690
6778
|
"""
|
6691
6779
|
|
6692
6780
|
if isinstance(newpath, Path):
|
@@ -6696,7 +6784,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
6696
6784
|
self.filename = newpath
|
6697
6785
|
|
6698
6786
|
if self.filename.endswith('.tif'):
|
6699
|
-
self.export_geotif()
|
6787
|
+
self.export_geotif(EPSG=EPSG)
|
6700
6788
|
elif self.filename.endswith('.npy'):
|
6701
6789
|
|
6702
6790
|
writing_header = True
|
@@ -6730,18 +6818,26 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
6730
6818
|
self.write_txt_header()
|
6731
6819
|
self.write_array()
|
6732
6820
|
|
6733
|
-
def
|
6821
|
+
def get_rebin_shape_size(self, factor:float) -> tuple[tuple[int, int], tuple[float, float]]:
|
6734
6822
|
"""
|
6735
|
-
|
6823
|
+
Return the new shape after rebinning.
|
6736
6824
|
|
6737
|
-
|
6825
|
+
newdx = dx * factor
|
6826
|
+
newdy = dy * factor
|
6738
6827
|
|
6739
|
-
|
6828
|
+
The shape is adjusted to be a multiple of the factor.
|
6829
|
+
|
6830
|
+
:param factor: factor of resolution change -- > 1.0 : decrease resolution, < 1.0 : increase resolution
|
6831
|
+
:type factor: float
|
6832
|
+
:return: new shape
|
6833
|
+
:rtype: Tuple[int, int]
|
6740
6834
|
"""
|
6741
|
-
operation = operation.lower()
|
6742
|
-
if not operation in ['sum', 'mean', 'min']:
|
6743
|
-
raise ValueError("Operator not supported.")
|
6744
6835
|
|
6836
|
+
newdx = self.dx * float(factor)
|
6837
|
+
newdy = self.dy * float(factor)
|
6838
|
+
|
6839
|
+
newnbx = self.nbx
|
6840
|
+
newnby = self.nby
|
6745
6841
|
if np.mod(self.nbx,factor) != 0 or np.mod(self.nby,factor) != 0 :
|
6746
6842
|
newnbx = self.nbx
|
6747
6843
|
newnby = self.nby
|
@@ -6750,8 +6846,85 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
6750
6846
|
if np.mod(self.nby,factor) !=0:
|
6751
6847
|
newnby = self.nby + factor - np.mod(self.nby,factor)
|
6752
6848
|
|
6753
|
-
|
6849
|
+
newnbx = int(newnbx / factor)
|
6850
|
+
newnby = int(newnby / factor)
|
6851
|
+
|
6852
|
+
return (newnbx, newnby), (newdx, newdy)
|
6853
|
+
|
6854
|
+
def get_rebin_header(self, factor:float) -> header_wolf:
|
6855
|
+
"""
|
6856
|
+
Return a new header after rebinning.
|
6857
|
+
|
6858
|
+
:param factor: factor of resolution change -- > 1.0 : decrease resolution, < 1.0 : increase resolution
|
6859
|
+
:type factor: float
|
6860
|
+
|
6861
|
+
:return: new header
|
6862
|
+
:rtype: header_wolf
|
6863
|
+
"""
|
6864
|
+
|
6865
|
+
newshape, newdx_dy = self.get_rebin_shape_size(factor)
|
6866
|
+
|
6867
|
+
newheader = self.get_header()
|
6868
|
+
|
6869
|
+
newheader.nbx = newshape[0]
|
6870
|
+
newheader.nby = newshape[1]
|
6871
|
+
newheader.dx = newdx_dy[0]
|
6872
|
+
newheader.dy = newdx_dy[1]
|
6873
|
+
|
6874
|
+
return newheader
|
6875
|
+
|
6876
|
+
def rebin(self,
|
6877
|
+
factor:float,
|
6878
|
+
operation:Literal['mean', 'sum', 'min', 'max', 'median'] ='mean',
|
6879
|
+
operation_matrix:"WolfArray"=None) -> None:
|
6880
|
+
"""
|
6881
|
+
Change resolution - **in place**.
|
6882
|
+
|
6883
|
+
If you want to keep current data, copy the WolfArray into a new variable -> newWA = Wolfarray(mold=curWA).
|
6884
|
+
|
6885
|
+
:param factor: factor of resolution change -- > 1.0 : decrease resolution, < 1.0 : increase resolution
|
6886
|
+
:type factor: float
|
6887
|
+
:param operation: operation to apply on the blocks ('mean', 'sum', 'min', 'max', 'median')
|
6888
|
+
:type operation: str, Rebin_Ops
|
6889
|
+
:param operation_matrix: operation matrix to apply on the blocks -- see the Enum "Rebin_Ops" for more infos. The matrix must have the same shape as the new array
|
6890
|
+
:type operation_matrix: WolfArray
|
6891
|
+
|
6892
|
+
"""
|
6893
|
+
|
6894
|
+
if operation_matrix is not None:
|
6895
|
+
tmp_header = self.get_rebin_header(factor)
|
6896
|
+
if not operation_matrix.is_like(tmp_header):
|
6897
|
+
logging.error(_("The operation matrix must have the same shape as the new array"))
|
6898
|
+
logging.info(_("You can use the get_rebin_header method to get the new header if you don't know it"))
|
6899
|
+
return
|
6900
|
+
|
6901
|
+
logging.info(_("Operation matrix detected"))
|
6902
|
+
logging.info(_("The operation matrix will be used to apply the operation on the blocks"))
|
6903
|
+
else:
|
6904
|
+
|
6905
|
+
operation = Rebin_Ops.get_ops(operation)
|
6906
|
+
|
6907
|
+
if operation is None:
|
6908
|
+
logging.error(_("Operator not supported -- Must be a string in ['sum', 'mean', 'min', 'max', 'median'] or a Rebin_Ops Enum"))
|
6909
|
+
return
|
6910
|
+
|
6911
|
+
if not callable(operation):
|
6912
|
+
logging.error(_("Operator not supported -- Must be a string in ['sum', 'mean', 'min', 'max', 'median'] or a Rebin_Ops Enum"))
|
6913
|
+
|
6914
|
+
|
6915
|
+
if np.mod(self.nbx,factor) != 0 or np.mod(self.nby,factor) != 0 :
|
6916
|
+
# The shape is adjusted to be a multiple of the factor.
|
6917
|
+
# Fill the array with nullvalue
|
6918
|
+
newnbx = self.nbx
|
6919
|
+
newnby = self.nby
|
6920
|
+
if np.mod(self.nbx,factor) !=0:
|
6921
|
+
newnbx = int(self.nbx + factor - np.mod(self.nbx,factor))
|
6922
|
+
if np.mod(self.nby,factor) !=0:
|
6923
|
+
newnby = int(self.nby + factor - np.mod(self.nby,factor))
|
6924
|
+
|
6925
|
+
newarray = np.ma.ones((newnbx,newnby), dtype = self.dtype) * self.nullvalue
|
6754
6926
|
newarray[:self.nbx,:self.nby] = self.array
|
6927
|
+
newarray.mask[:self.nbx,:self.nby] = self.array.mask
|
6755
6928
|
self.array = newarray
|
6756
6929
|
|
6757
6930
|
self.nbx = newnbx
|
@@ -6765,20 +6938,41 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
6765
6938
|
new_shape = (self.nbx, self.nby)
|
6766
6939
|
|
6767
6940
|
if factor>1.:
|
6768
|
-
|
6769
|
-
|
6770
|
-
|
6771
|
-
|
6772
|
-
|
6773
|
-
|
6774
|
-
|
6941
|
+
if operation_matrix is not None:
|
6942
|
+
# Reshape the input array to split it into blocks of size f x f
|
6943
|
+
reshaped_a = self.array.reshape(new_shape[0], int(factor), new_shape[1], int(factor))
|
6944
|
+
|
6945
|
+
# Swap axes to make blocks as separate dimensions
|
6946
|
+
reshaped_a = reshaped_a.swapaxes(1, 2)
|
6947
|
+
|
6948
|
+
# Initialize the output matrix
|
6949
|
+
self.array = ma.masked_array(np.ones((new_shape[0], new_shape[1]), dtype= self.dtype) * self.nullvalue, dtype= self.dtype)
|
6950
|
+
|
6951
|
+
# Check the dtype of the newly initialized array
|
6952
|
+
assert self.array.dtype == self.dtype, _('Bad dtype')
|
6953
|
+
|
6954
|
+
# Vectorized operations
|
6955
|
+
for op_idx, operation in enumerate(Rebin_Ops.get_numpy_ops()):
|
6956
|
+
mask = (operation_matrix.array == op_idx)
|
6957
|
+
if np.any(mask):
|
6958
|
+
block_results = operation(reshaped_a, axis=(2, 3))
|
6959
|
+
self.array[mask] = block_results[mask]
|
6960
|
+
|
6961
|
+
else:
|
6962
|
+
compression_pairs = [(d, c // d) for d, c in zip(new_shape,
|
6963
|
+
self.array.shape)]
|
6964
|
+
flattened = [l for p in compression_pairs for l in p]
|
6965
|
+
self.array = operation(self.array.reshape(flattened), axis=(1, 3)).astype(self.dtype)
|
6966
|
+
|
6967
|
+
self.set_nullvalue_in_mask()
|
6775
6968
|
else:
|
6776
6969
|
self.array = np.kron(self.array, np.ones((int(1/factor), int(1/factor)), dtype=self.array.dtype))
|
6777
6970
|
|
6778
|
-
self.mask_reset()
|
6779
|
-
|
6780
6971
|
self.count()
|
6781
6972
|
|
6973
|
+
# rebin must not change the type of the array
|
6974
|
+
assert self.array.dtype == self.dtype, _('Bad dtype')
|
6975
|
+
|
6782
6976
|
def read_txt_header(self):
|
6783
6977
|
"""
|
6784
6978
|
Read header from txt file
|
@@ -8001,6 +8195,54 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
8001
8195
|
|
8002
8196
|
self.reset_plot()
|
8003
8197
|
|
8198
|
+
@classmethod
|
8199
|
+
def from_other_epsg_coo(cls,
|
8200
|
+
input_raster_path:str,
|
8201
|
+
input_srs='EPSG:3812',
|
8202
|
+
output_srs='EPSG:31370',
|
8203
|
+
resampling_method=gdal.GRA_Bilinear,
|
8204
|
+
xRes:float=0.5, yRes:float=0.5):
|
8205
|
+
"""
|
8206
|
+
Reprojects and resamples a raster file from an other EPSG coordinates and return it as a WolfArray.
|
8207
|
+
|
8208
|
+
:param input_raster_path: The path to the input raster file.
|
8209
|
+
:type input_raster_path: str
|
8210
|
+
:param input_srs: The input spatial reference system (SRS) in the format 'EPSG:XXXX'. Defaults to Lambert 2008 'EPSG:3812'.
|
8211
|
+
:type input_srs: str
|
8212
|
+
:param output_srs: The output spatial reference system (SRS) in the format 'EPSG:XXXX'. Defaults to Belgian Lambert 72 'EPSG:31370'.
|
8213
|
+
:type output_srs: str
|
8214
|
+
:param resampling_method: The resampling method to use. Defaults to gdal.GRA_Bilinear. Resampling method can be chosen among the gdal GRA_*
|
8215
|
+
constants (gdal.GRA_Average; gdal.GRA_Bilinear; gdal.GRA_Cubic; gdal.GRA_CubicSpline;
|
8216
|
+
gdal.GRA_Lanczos; gdal.GRA_Mode; gdal.GRA_NearestNeighbour)
|
8217
|
+
:type resampling_method: int
|
8218
|
+
:param xRes: The desired output resolution in the x direction. Defaults to 0.5.
|
8219
|
+
:type xRes (float): float
|
8220
|
+
:param yRes: The desired output resolution in the y direction. Defaults to 0.5.
|
8221
|
+
:type yRes (float): float
|
8222
|
+
|
8223
|
+
:raises AssertionError: If the input or output raster file is not a GeoTIFF file.
|
8224
|
+
:raises RuntimeError: If the input raster file cannot be opened.
|
8225
|
+
:raises PermissionError: If there is a permission error while trying to delete the output raster file.
|
8226
|
+
:raises Exception: If an unexpected error occurs while trying to delete the output raster file.
|
8227
|
+
:raises RuntimeError: If the reprojection fails for the input raster file.
|
8228
|
+
|
8229
|
+
:return: WolfArray
|
8230
|
+
"""
|
8231
|
+
|
8232
|
+
#sanitize input
|
8233
|
+
input_raster_path = str(input_raster_path)
|
8234
|
+
input_srs = str(input_srs)
|
8235
|
+
output_srs = str(output_srs)
|
8236
|
+
|
8237
|
+
assert resampling_method in [gdal.GRA_Average, gdal.GRA_Bilinear, gdal.GRA_Cubic, gdal.GRA_CubicSpline, gdal.GRA_Lanczos, gdal.GRA_Mode, gdal.GRA_NearestNeighbour], "Invalid resampling method"
|
8238
|
+
|
8239
|
+
# Define temporary files
|
8240
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
8241
|
+
output_raster_path = os.path.join(temp_dir, "Array_72.tif")
|
8242
|
+
reproject_and_resample_raster(input_raster_path, output_raster_path, input_srs, output_srs, resampling_method, xRes, yRes)
|
8243
|
+
Array3 = WolfArray(output_raster_path, nullvalue=-9999)
|
8244
|
+
return Array3
|
8245
|
+
|
8004
8246
|
class WolfArrayMB(WolfArray):
|
8005
8247
|
"""
|
8006
8248
|
Matrice multiblocks
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: wolfhece
|
3
|
-
Version: 2.1.
|
3
|
+
Version: 2.1.49
|
4
4
|
Author-email: Pierre Archambeau <pierre.archambeau@uliege.be>
|
5
5
|
License: Copyright (c) 2024 University of Liege. All rights reserved.
|
6
6
|
Project-URL: Homepage, https://uee.uliege.be/hece
|
@@ -13,14 +13,14 @@ Classifier: Topic :: Scientific/Engineering :: Physics
|
|
13
13
|
Requires-Python: <3.11,>=3.10
|
14
14
|
Description-Content-Type: text/markdown
|
15
15
|
Requires-Dist: wxpython
|
16
|
-
Requires-Dist: colorlog
|
16
|
+
Requires-Dist: colorlog ==6.7.*
|
17
17
|
Requires-Dist: intel-fortran-rt
|
18
18
|
Requires-Dist: scikit-learn
|
19
19
|
Requires-Dist: cryptography
|
20
|
-
Requires-Dist: jax
|
20
|
+
Requires-Dist: jax ==0.4.30
|
21
21
|
Requires-Dist: triangle
|
22
|
-
Requires-Dist: numpy
|
23
|
-
Requires-Dist: pyopengl
|
22
|
+
Requires-Dist: numpy ==1.23.*
|
23
|
+
Requires-Dist: pyopengl ==3.1.*
|
24
24
|
Requires-Dist: pandas
|
25
25
|
Requires-Dist: geopandas
|
26
26
|
Requires-Dist: scipy
|
@@ -33,7 +33,7 @@ Requires-Dist: graphviz
|
|
33
33
|
Requires-Dist: beautifulsoup4
|
34
34
|
Requires-Dist: requests
|
35
35
|
Requires-Dist: notebook
|
36
|
-
Requires-Dist: matplotlib
|
36
|
+
Requires-Dist: matplotlib ==3.6.*
|
37
37
|
Requires-Dist: mkl
|
38
38
|
Requires-Dist: python-gettext
|
39
39
|
Requires-Dist: shapely
|
@@ -49,10 +49,10 @@ Requires-Dist: python-docx
|
|
49
49
|
Requires-Dist: pygltflib
|
50
50
|
Requires-Dist: ezdxf
|
51
51
|
Requires-Dist: pyvista
|
52
|
-
Requires-Dist: tqdm
|
52
|
+
Requires-Dist: tqdm ==4.64.*
|
53
53
|
Requires-Dist: osmnx
|
54
54
|
Requires-Dist: tifffile
|
55
|
-
Requires-Dist: numba
|
55
|
+
Requires-Dist: numba ==0.58.*
|
56
56
|
Requires-Dist: xmltodict
|
57
57
|
Requires-Dist: opencv-python
|
58
58
|
Requires-Dist: xarray
|
@@ -1,3 +1,4 @@
|
|
1
|
+
wolfhece/Coordinates_operations.py,sha256=YyWlAwKManb-ReQrmP37rEXxehunUCihmkeDYX6qTAQ,8037
|
1
2
|
wolfhece/CpGrid.py,sha256=ke4n1khTUoed2asJl1GR25PsEkI4TpiBDCo4u0aSo9M,10658
|
2
3
|
wolfhece/GraphNotebook.py,sha256=V1_Ak4F_hoIpKm2GAakuyKOALhujjIXB5FwzFHtM5-8,28021
|
3
4
|
wolfhece/GraphProfile.py,sha256=OCgJo0YFFBI6H1z-5egJsOOoWF_iziiza0-bbPejNMc,69656
|
@@ -6,7 +7,7 @@ wolfhece/ManageParams.py,sha256=EeuUI5Vvh9ixCvYf8YShMC1s1Yacc7OxOCN7q81gqiQ,517
|
|
6
7
|
wolfhece/Model1D.py,sha256=uL1DJVmDI2xVSE7H6n3icn3QbsPtTHeg8E-6wkDloKw,476914
|
7
8
|
wolfhece/PyConfig.py,sha256=FB8u0belXOXTb03Ln6RdVWvMgjzi3oGPCmw2dWa3lNg,8332
|
8
9
|
wolfhece/PyCrosssections.py,sha256=FnmM9DWY_SAF2EDH9Gu2PojXNtSTRF4-aYQuAAJXBh4,112771
|
9
|
-
wolfhece/PyDraw.py,sha256=
|
10
|
+
wolfhece/PyDraw.py,sha256=_Rfx59LMopR0Cx00d1RRF5Gb-WNxfA2v2RjkOfm84Yo,390847
|
10
11
|
wolfhece/PyGui.py,sha256=aRWv9tBpRl7sKEd2gHWj8Bss0ZOKbGlUYIehWHFm8WY,105008
|
11
12
|
wolfhece/PyGuiHydrology.py,sha256=f60E8K9eGTnRq5RDF6yvt-ahf2AYegwQ9t25zZ2Mk1A,14946
|
12
13
|
wolfhece/PyHydrographs.py,sha256=jwtSNMMACwarxrtN1UeQYth99UNrhwPx1IGgUwcooHA,3774
|
@@ -15,7 +16,7 @@ wolfhece/PyParams.py,sha256=wwgmP-_7wiiPLTcyX8a5jR6FyC1D2c4oBPc1VWQqtSA,97383
|
|
15
16
|
wolfhece/PyPictures.py,sha256=m1kY0saW6Y9Q0bDCo47lW6XxDkBrbQG-Fd8uVn8G5ic,2514
|
16
17
|
wolfhece/PyTranslate.py,sha256=4appkmNeHHZLFmUtaA_k5_5QL-5ymxnbVN4R2OblmtE,622
|
17
18
|
wolfhece/PyVertex.py,sha256=vJ-NbnhPiTuFvDfAF7wfrEzVmladx5Ts0zKsyfySV3Q,40390
|
18
|
-
wolfhece/PyVertexvectors.py,sha256=
|
19
|
+
wolfhece/PyVertexvectors.py,sha256=KMXJB_zFi54I73jk_fGtSTxqTQhnCwngeEjJyLdgGDo,235914
|
19
20
|
wolfhece/PyWMS.py,sha256=fyyzm2HFwq8aRwVYHKiBatcZOeKnFi6DWhv4nfscySQ,4602
|
20
21
|
wolfhece/RatingCurve.py,sha256=bUjIrQjvIjkD4V-z8bZmA6pe1ILtYNM0-3fT6YUY1RU,22498
|
21
22
|
wolfhece/RatingCurveData.py,sha256=5UvnIm89BwqjnEbLCcY3CA8WoFd_xHJbooNy62fX5iY,57660
|
@@ -26,7 +27,7 @@ wolfhece/__init__.py,sha256=FRDE8PiJAWxX9PMXsShRMZ8YADAY4WIgKMRh52rmhiw,23
|
|
26
27
|
wolfhece/_add_path.py,sha256=nudniS-lsgHwXXq5o626XRDzIeYj76GoGKYt6lcu2Nc,616
|
27
28
|
wolfhece/cli.py,sha256=3S1Hbp2tOl51LwLcloAm1DqV9QuUWJx_Ui_vdKNtGxo,2915
|
28
29
|
wolfhece/color_constants.py,sha256=Snc5RX11Ydi756EkBp_83C7DiAQ_Z1aHD9jFIBsosAU,37121
|
29
|
-
wolfhece/drawing_obj.py,sha256=
|
30
|
+
wolfhece/drawing_obj.py,sha256=7vY04B6r08nurTTFmBXHyR5tVIF1YzAEw_uz4pqTDIw,4233
|
30
31
|
wolfhece/flow_SPWMI.py,sha256=XDAelwAY-3rYOR0WKW3fgYJ_r8DU4IP6Y5xULW421tk,20956
|
31
32
|
wolfhece/friction_law.py,sha256=MtZJLo-pTj3-Fw-w12z1LSgSIDrH-JGR0iD9wer_fpQ,5498
|
32
33
|
wolfhece/gpuview.py,sha256=0Ld8glEijx5OhMEfcwqvUFEQ5ryRXLnzey3Dff_sn-k,24110
|
@@ -47,7 +48,7 @@ wolfhece/pywalous.py,sha256=yRaWJjKckXef1d9D5devP0yFHC9uc6kRV4G5x9PNq9k,18972
|
|
47
48
|
wolfhece/rain_SPWMI.py,sha256=qCfcmF7LajloOaCwnTrrSMzyME03YyilmRUOqrPrv3U,13846
|
48
49
|
wolfhece/textpillow.py,sha256=map7HsGYML_o5NHRdFg2s_TVQed_lDnpYNDv27MM0Vw,14130
|
49
50
|
wolfhece/tools_mpl.py,sha256=gQ3Jg1iuZiecmMqa5Eli2ZLSkttu68VXL8YmMDBaEYU,564
|
50
|
-
wolfhece/wolf_array.py,sha256=
|
51
|
+
wolfhece/wolf_array.py,sha256=HnrviXNSps9LFDERXyeZmI0L2ovFYY4rBHInPBZLRGw,368994
|
51
52
|
wolfhece/wolf_hist.py,sha256=7jeVrgSkM3ErJO6SRMH_PGzfLjIdw8vTy87kesldggk,3582
|
52
53
|
wolfhece/wolf_texture.py,sha256=DS5eobLxrq9ljyebYfpMSQPn8shkUAZZVfqrOKN_QUU,16951
|
53
54
|
wolfhece/wolf_tiles.py,sha256=2Ho2I20rHRY81KXxjgLOYISdF4OkJ2d6omeY4shDoGI,10386
|
@@ -71,7 +72,7 @@ wolfhece/apps/check_install.py,sha256=SG024u18G7VRLKynbp7DKD1jImtHwuWwN4bJWHm-YH
|
|
71
72
|
wolfhece/apps/curvedigitizer.py,sha256=_hRR2PWow7PU7rTHIbc6ykZ08tCXcK9uy7RFrb4EKkE,5196
|
72
73
|
wolfhece/apps/isocurrent.py,sha256=MuwTodHxdc6PrqNpphR2ntYf1NLL2n9klTPndGrOHDQ,4109
|
73
74
|
wolfhece/apps/splashscreen.py,sha256=SrustmIQeXnsiD-92OzjdGhBi-S7c_j-cSvuX4T6rtg,2929
|
74
|
-
wolfhece/apps/version.py,sha256=
|
75
|
+
wolfhece/apps/version.py,sha256=cUwL_sNDbbwu6AtD4FZAGrhp2E-myuuGl2doXoLXtBc,388
|
75
76
|
wolfhece/apps/wolf.py,sha256=mM6Tyi4DlKQILmO49cDUCip9fYVy-hLXkY3YhZgIeUQ,591
|
76
77
|
wolfhece/apps/wolf2D.py,sha256=yPQGee7fsegoQ8GfWKrWEjX1Az_ApL-UWlBiqPvaIyY,565
|
77
78
|
wolfhece/apps/wolf_logo.bmp,sha256=ruJ4MA51CpGO_AYUp_dB4SWKHelvhOvd7Q8NrVOjDJk,3126
|
@@ -277,8 +278,8 @@ wolfhece/ui/wolf_multiselection_collapsiblepane.py,sha256=8PlMYrb_8jI8h9F0_EagpM
|
|
277
278
|
wolfhece/ui/wolf_times_selection_comparison_models.py,sha256=ORy7fz4dcp691qKzaOZHrRLZ0uXNhL-LIHxmpDGL6BI,5007
|
278
279
|
wolfhece/wintab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
279
280
|
wolfhece/wintab/wintab.py,sha256=8A-JNONV6ujgsgG3lM5Uw-pVgglPATwKs86oBzzljoc,7179
|
280
|
-
wolfhece-2.1.
|
281
|
-
wolfhece-2.1.
|
282
|
-
wolfhece-2.1.
|
283
|
-
wolfhece-2.1.
|
284
|
-
wolfhece-2.1.
|
281
|
+
wolfhece-2.1.49.dist-info/METADATA,sha256=5OMCtgg9J68-JovF2B1Yy4PdFja_n8nT7_UTT_vlgsU,2548
|
282
|
+
wolfhece-2.1.49.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
283
|
+
wolfhece-2.1.49.dist-info/entry_points.txt,sha256=Q5JuIWV4odeIJI3qc6fV9MwRoz0ezqPVlFC1Ppm_vdQ,395
|
284
|
+
wolfhece-2.1.49.dist-info/top_level.txt,sha256=EfqZXMVCn7eILUzx9xsEu2oBbSo9liWPFWjIHik0iCI,9
|
285
|
+
wolfhece-2.1.49.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|