wolfhece 2.1.45__py3-none-any.whl → 2.1.48__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 +4 -0
- wolfhece/apps/version.py +1 -1
- wolfhece/scenario/config_manager.py +5 -0
- wolfhece/wolf_array.py +303 -38
- {wolfhece-2.1.45.dist-info → wolfhece-2.1.48.dist-info}/METADATA +8 -8
- {wolfhece-2.1.45.dist-info → wolfhece-2.1.48.dist-info}/RECORD +10 -9
- {wolfhece-2.1.45.dist-info → wolfhece-2.1.48.dist-info}/WHEEL +0 -0
- {wolfhece-2.1.45.dist-info → wolfhece-2.1.48.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.1.45.dist-info → wolfhece-2.1.48.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
@@ -7508,6 +7508,8 @@ class WolfMapViewer(wx.Frame):
|
|
7508
7508
|
if self.active_array.nb_blocks > 0:
|
7509
7509
|
txt += ' ; Nb blocks : {:d}'.format(self.active_array.nb_blocks)
|
7510
7510
|
|
7511
|
+
txt += ' ; Type : ' + self.active_array.dtype_str
|
7512
|
+
|
7511
7513
|
self.StatusBar.SetStatusText(txt)
|
7512
7514
|
|
7513
7515
|
|
@@ -8393,6 +8395,8 @@ class WolfMapViewer(wx.Frame):
|
|
8393
8395
|
if not altdown:
|
8394
8396
|
newarray.mask_outsidepoly(self.active_vector)
|
8395
8397
|
|
8398
|
+
newarray.nullify_border(width=1)
|
8399
|
+
|
8396
8400
|
self.add_object('array', newobj = newarray, id = self.active_array.idx + '_crop')
|
8397
8401
|
|
8398
8402
|
self.Refresh()
|
wolfhece/apps/version.py
CHANGED
@@ -746,6 +746,7 @@ class Config_Manager_2D_GPU:
|
|
746
746
|
new_zones.add_zone(new_zone)
|
747
747
|
|
748
748
|
curarray = WolfArray(curtif)
|
749
|
+
curarray.nullify_border(width=1)
|
749
750
|
sux, sux, curvect, interior = curarray.suxsuy_contour()
|
750
751
|
new_zone.add_vector(curvect, forceparent=True)
|
751
752
|
curvect.set_legend_to_centroid(curtif.name)
|
@@ -1481,6 +1482,10 @@ class UI_Manager_2D_GPU():
|
|
1481
1482
|
logging.info(_('Creating vecz ...'))
|
1482
1483
|
mydata = self._treelist.GetItemData(self._selected_item)
|
1483
1484
|
|
1485
|
+
if not 'path' in mydata:
|
1486
|
+
logging.error(_('Please select a scenario to analyze !'))
|
1487
|
+
return
|
1488
|
+
|
1484
1489
|
# création du fichier vrt
|
1485
1490
|
new_zones = self._parent.create_vec(mydata['path'])
|
1486
1491
|
logging.info(_('... done !'))
|
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
|
@@ -4396,14 +4440,24 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4396
4440
|
|
4397
4441
|
def __del__(self):
|
4398
4442
|
""" Destructeur de la classe """
|
4399
|
-
|
4400
|
-
|
4401
|
-
|
4402
|
-
|
4403
|
-
|
4404
|
-
|
4405
|
-
|
4406
|
-
|
4443
|
+
try:
|
4444
|
+
# Perform cleanup tasks safely
|
4445
|
+
self.delete_lists()
|
4446
|
+
if hasattr(self, 'array'):
|
4447
|
+
del self.array
|
4448
|
+
if VERSION_RGB == 1 and hasattr(self, 'rgb'):
|
4449
|
+
del self.rgb
|
4450
|
+
if hasattr(self, '_array3d'):
|
4451
|
+
del self._array3d
|
4452
|
+
if hasattr(self, 'mypal'):
|
4453
|
+
del self.mypal
|
4454
|
+
if hasattr(self, 'shaded'):
|
4455
|
+
del self.shaded
|
4456
|
+
# Perform garbage collection if gc is available
|
4457
|
+
import gc
|
4458
|
+
gc.collect()
|
4459
|
+
except Exception as e:
|
4460
|
+
print(f"Exception in WolfArray destructor: {e} -- Please report this issue")
|
4407
4461
|
|
4408
4462
|
def extract_selection(self):
|
4409
4463
|
""" Extract the current selection """
|
@@ -4613,6 +4667,36 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4613
4667
|
|
4614
4668
|
return dtype
|
4615
4669
|
|
4670
|
+
@property
|
4671
|
+
def dtype_str(self):
|
4672
|
+
"""
|
4673
|
+
Return the numpy dtype corresponding to the WOLF type, as a string
|
4674
|
+
|
4675
|
+
Pay ettention to the difference between :
|
4676
|
+
- LOGICAL : Fortran and VB6
|
4677
|
+
- Bool : Python
|
4678
|
+
|
4679
|
+
In VB6, logical is stored as int16
|
4680
|
+
In Fortran, there are Logical*1, Logical*2, Logical*4, Logical*8
|
4681
|
+
In Python, bool is one byte
|
4682
|
+
In Numpy, np.bool_ is one byte
|
4683
|
+
"""
|
4684
|
+
|
4685
|
+
if self.wolftype in [WOLF_ARRAY_FULL_DOUBLE, WOLF_ARRAY_SYM_DOUBLE, WOLF_ARRAY_CSR_DOUBLE]:
|
4686
|
+
dtype = _('float64 - 8 bytes poer values')
|
4687
|
+
elif self.wolftype in [WOLF_ARRAY_FULL_SINGLE, WOLF_ARRAY_FULL_SINGLE_3D, WOLF_ARRAY_MB_SINGLE]:
|
4688
|
+
dtype = _('float32 - 4 bytes per values')
|
4689
|
+
elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER, WOLF_ARRAY_MB_INTEGER, WOLF_ARRAY_MNAP_INTEGER]:
|
4690
|
+
dtype = _('int32 - 4 bytes per values')
|
4691
|
+
elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER16, WOLF_ARRAY_FULL_INTEGER16_2]:
|
4692
|
+
dtype = _('int16 - 2 bytes per values')
|
4693
|
+
elif self.wolftype == WOLF_ARRAY_FULL_INTEGER8:
|
4694
|
+
dtype = _('int8 - 1 byte per values')
|
4695
|
+
elif self.wolftype == WOLF_ARRAY_FULL_LOGICAL:
|
4696
|
+
dtype = _('int16 - 2 bytes per values')
|
4697
|
+
|
4698
|
+
return dtype
|
4699
|
+
|
4616
4700
|
def loadnap_and_apply(self):
|
4617
4701
|
"""
|
4618
4702
|
Load a mask file (aka nap) and apply it to the array;
|
@@ -4772,7 +4856,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4772
4856
|
if reset_plot:
|
4773
4857
|
self.reset_plot()
|
4774
4858
|
|
4775
|
-
def export_geotif(self, outdir='', extent = ''):
|
4859
|
+
def export_geotif(self, outdir='', extent = '', EPSG:int = 31370):
|
4776
4860
|
"""
|
4777
4861
|
Export de la matrice au format Geotiff (Lambert 72 - EPSG:31370)
|
4778
4862
|
|
@@ -4783,11 +4867,12 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4783
4867
|
|
4784
4868
|
:param outdir: directory
|
4785
4869
|
:param extent: suffix to add to the filename before the extension '.tif'
|
4870
|
+
:param EPSG: EPSG code, by default 31370 (Lambert 72)
|
4786
4871
|
"""
|
4787
4872
|
from osgeo import gdal, osr, gdalconst
|
4788
4873
|
|
4789
4874
|
srs = osr.SpatialReference()
|
4790
|
-
srs.ImportFromEPSG(
|
4875
|
+
srs.ImportFromEPSG(EPSG)
|
4791
4876
|
|
4792
4877
|
if outdir=='' and extent=='':
|
4793
4878
|
filename = self.filename
|
@@ -4815,7 +4900,17 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
4815
4900
|
out_ds: gdal.Dataset
|
4816
4901
|
band: gdal.Band
|
4817
4902
|
driver = gdal.GetDriverByName("GTiff")
|
4818
|
-
|
4903
|
+
# bytes_per_pixel = arr.data.dtype.itemsize
|
4904
|
+
estimated_file_size = self.memory_usage #arr.shape[0] * arr.shape[1] * bytes_per_pixel
|
4905
|
+
|
4906
|
+
# Check if estimated file size exceeds 4GB
|
4907
|
+
if (estimated_file_size > 4 * 1024**3): # 4GB in bytes
|
4908
|
+
options = ['COMPRESS=LZW', 'BIGTIFF=YES']
|
4909
|
+
print('BigTIFF format will be used!')
|
4910
|
+
else:
|
4911
|
+
options = ['COMPRESS=LZW']
|
4912
|
+
|
4913
|
+
out_ds = driver.Create(filename, arr.shape[0], arr.shape[1], 1, arr_type, options=options)
|
4819
4914
|
out_ds.SetProjection(srs.ExportToWkt())
|
4820
4915
|
|
4821
4916
|
|
@@ -5079,6 +5174,10 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
5079
5174
|
except:
|
5080
5175
|
logging.warning(_('Error during importing tif file'))
|
5081
5176
|
|
5177
|
+
# Close the raster
|
5178
|
+
raster.FlushCache()
|
5179
|
+
raster = None
|
5180
|
+
|
5082
5181
|
def add_ops_sel(self):
|
5083
5182
|
"""
|
5084
5183
|
Adding selection manager and operations array
|
@@ -6652,11 +6751,12 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
6652
6751
|
if update_min_max:
|
6653
6752
|
self.mypal.distribute_values(self.array.min(), self.array.max())
|
6654
6753
|
|
6655
|
-
def write_all(self, newpath:str = None):
|
6754
|
+
def write_all(self, newpath:str = None, EPSG:int = 31370):
|
6656
6755
|
"""
|
6657
6756
|
Ecriture de tous les fichiers d'un Wolf array
|
6658
6757
|
|
6659
6758
|
:param newpath: new path and filename with extension -- if None, use the current filename
|
6759
|
+
:param EPSG: EPSG code for geotiff
|
6660
6760
|
"""
|
6661
6761
|
|
6662
6762
|
if isinstance(newpath, Path):
|
@@ -6666,7 +6766,7 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
6666
6766
|
self.filename = newpath
|
6667
6767
|
|
6668
6768
|
if self.filename.endswith('.tif'):
|
6669
|
-
self.export_geotif()
|
6769
|
+
self.export_geotif(EPSG=EPSG)
|
6670
6770
|
elif self.filename.endswith('.npy'):
|
6671
6771
|
|
6672
6772
|
writing_header = True
|
@@ -6700,18 +6800,26 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
6700
6800
|
self.write_txt_header()
|
6701
6801
|
self.write_array()
|
6702
6802
|
|
6703
|
-
def
|
6803
|
+
def get_rebin_shape_size(self, factor:float) -> tuple[tuple[int, int], tuple[float, float]]:
|
6704
6804
|
"""
|
6705
|
-
|
6805
|
+
Return the new shape after rebinning.
|
6706
6806
|
|
6707
|
-
|
6807
|
+
newdx = dx * factor
|
6808
|
+
newdy = dy * factor
|
6809
|
+
|
6810
|
+
The shape is adjusted to be a multiple of the factor.
|
6708
6811
|
|
6709
|
-
|
6812
|
+
:param factor: factor of resolution change -- > 1.0 : decrease resolution, < 1.0 : increase resolution
|
6813
|
+
:type factor: float
|
6814
|
+
:return: new shape
|
6815
|
+
:rtype: Tuple[int, int]
|
6710
6816
|
"""
|
6711
|
-
operation = operation.lower()
|
6712
|
-
if not operation in ['sum', 'mean', 'min']:
|
6713
|
-
raise ValueError("Operator not supported.")
|
6714
6817
|
|
6818
|
+
newdx = self.dx * float(factor)
|
6819
|
+
newdy = self.dy * float(factor)
|
6820
|
+
|
6821
|
+
newnbx = self.nbx
|
6822
|
+
newnby = self.nby
|
6715
6823
|
if np.mod(self.nbx,factor) != 0 or np.mod(self.nby,factor) != 0 :
|
6716
6824
|
newnbx = self.nbx
|
6717
6825
|
newnby = self.nby
|
@@ -6720,8 +6828,85 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
6720
6828
|
if np.mod(self.nby,factor) !=0:
|
6721
6829
|
newnby = self.nby + factor - np.mod(self.nby,factor)
|
6722
6830
|
|
6723
|
-
|
6831
|
+
newnbx = int(newnbx / factor)
|
6832
|
+
newnby = int(newnby / factor)
|
6833
|
+
|
6834
|
+
return (newnbx, newnby), (newdx, newdy)
|
6835
|
+
|
6836
|
+
def get_rebin_header(self, factor:float) -> header_wolf:
|
6837
|
+
"""
|
6838
|
+
Return a new header after rebinning.
|
6839
|
+
|
6840
|
+
:param factor: factor of resolution change -- > 1.0 : decrease resolution, < 1.0 : increase resolution
|
6841
|
+
:type factor: float
|
6842
|
+
|
6843
|
+
:return: new header
|
6844
|
+
:rtype: header_wolf
|
6845
|
+
"""
|
6846
|
+
|
6847
|
+
newshape, newdx_dy = self.get_rebin_shape_size(factor)
|
6848
|
+
|
6849
|
+
newheader = self.get_header()
|
6850
|
+
|
6851
|
+
newheader.nbx = newshape[0]
|
6852
|
+
newheader.nby = newshape[1]
|
6853
|
+
newheader.dx = newdx_dy[0]
|
6854
|
+
newheader.dy = newdx_dy[1]
|
6855
|
+
|
6856
|
+
return newheader
|
6857
|
+
|
6858
|
+
def rebin(self,
|
6859
|
+
factor:float,
|
6860
|
+
operation:Literal['mean', 'sum', 'min', 'max', 'median'] ='mean',
|
6861
|
+
operation_matrix:"WolfArray"=None) -> None:
|
6862
|
+
"""
|
6863
|
+
Change resolution - **in place**.
|
6864
|
+
|
6865
|
+
If you want to keep current data, copy the WolfArray into a new variable -> newWA = Wolfarray(mold=curWA).
|
6866
|
+
|
6867
|
+
:param factor: factor of resolution change -- > 1.0 : decrease resolution, < 1.0 : increase resolution
|
6868
|
+
:type factor: float
|
6869
|
+
:param operation: operation to apply on the blocks ('mean', 'sum', 'min', 'max', 'median')
|
6870
|
+
:type operation: str, Rebin_Ops
|
6871
|
+
: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
|
6872
|
+
:type operation_matrix: WolfArray
|
6873
|
+
|
6874
|
+
"""
|
6875
|
+
|
6876
|
+
if operation_matrix is not None:
|
6877
|
+
tmp_header = self.get_rebin_header(factor)
|
6878
|
+
if not operation_matrix.is_like(tmp_header):
|
6879
|
+
logging.error(_("The operation matrix must have the same shape as the new array"))
|
6880
|
+
logging.info(_("You can use the get_rebin_header method to get the new header if you don't know it"))
|
6881
|
+
return
|
6882
|
+
|
6883
|
+
logging.info(_("Operation matrix detected"))
|
6884
|
+
logging.info(_("The operation matrix will be used to apply the operation on the blocks"))
|
6885
|
+
else:
|
6886
|
+
|
6887
|
+
operation = Rebin_Ops.get_ops(operation)
|
6888
|
+
|
6889
|
+
if operation is None:
|
6890
|
+
logging.error(_("Operator not supported -- Must be a string in ['sum', 'mean', 'min', 'max', 'median'] or a Rebin_Ops Enum"))
|
6891
|
+
return
|
6892
|
+
|
6893
|
+
if not callable(operation):
|
6894
|
+
logging.error(_("Operator not supported -- Must be a string in ['sum', 'mean', 'min', 'max', 'median'] or a Rebin_Ops Enum"))
|
6895
|
+
|
6896
|
+
|
6897
|
+
if np.mod(self.nbx,factor) != 0 or np.mod(self.nby,factor) != 0 :
|
6898
|
+
# The shape is adjusted to be a multiple of the factor.
|
6899
|
+
# Fill the array with nullvalue
|
6900
|
+
newnbx = self.nbx
|
6901
|
+
newnby = self.nby
|
6902
|
+
if np.mod(self.nbx,factor) !=0:
|
6903
|
+
newnbx = int(self.nbx + factor - np.mod(self.nbx,factor))
|
6904
|
+
if np.mod(self.nby,factor) !=0:
|
6905
|
+
newnby = int(self.nby + factor - np.mod(self.nby,factor))
|
6906
|
+
|
6907
|
+
newarray = np.ma.ones((newnbx,newnby), dtype = self.dtype) * self.nullvalue
|
6724
6908
|
newarray[:self.nbx,:self.nby] = self.array
|
6909
|
+
newarray.mask[:self.nbx,:self.nby] = self.array.mask
|
6725
6910
|
self.array = newarray
|
6726
6911
|
|
6727
6912
|
self.nbx = newnbx
|
@@ -6735,20 +6920,41 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
6735
6920
|
new_shape = (self.nbx, self.nby)
|
6736
6921
|
|
6737
6922
|
if factor>1.:
|
6738
|
-
|
6739
|
-
|
6740
|
-
|
6741
|
-
|
6742
|
-
|
6743
|
-
|
6744
|
-
|
6923
|
+
if operation_matrix is not None:
|
6924
|
+
# Reshape the input array to split it into blocks of size f x f
|
6925
|
+
reshaped_a = self.array.reshape(new_shape[0], int(factor), new_shape[1], int(factor))
|
6926
|
+
|
6927
|
+
# Swap axes to make blocks as separate dimensions
|
6928
|
+
reshaped_a = reshaped_a.swapaxes(1, 2)
|
6929
|
+
|
6930
|
+
# Initialize the output matrix
|
6931
|
+
self.array = ma.masked_array(np.ones((new_shape[0], new_shape[1]), dtype= self.dtype) * self.nullvalue, dtype= self.dtype)
|
6932
|
+
|
6933
|
+
# Check the dtype of the newly initialized array
|
6934
|
+
assert self.array.dtype == self.dtype, _('Bad dtype')
|
6935
|
+
|
6936
|
+
# Vectorized operations
|
6937
|
+
for op_idx, operation in enumerate(Rebin_Ops.get_numpy_ops()):
|
6938
|
+
mask = (operation_matrix.array == op_idx)
|
6939
|
+
if np.any(mask):
|
6940
|
+
block_results = operation(reshaped_a, axis=(2, 3))
|
6941
|
+
self.array[mask] = block_results[mask]
|
6942
|
+
|
6943
|
+
else:
|
6944
|
+
compression_pairs = [(d, c // d) for d, c in zip(new_shape,
|
6945
|
+
self.array.shape)]
|
6946
|
+
flattened = [l for p in compression_pairs for l in p]
|
6947
|
+
self.array = operation(self.array.reshape(flattened), axis=(1, 3)).astype(self.dtype)
|
6948
|
+
|
6949
|
+
self.set_nullvalue_in_mask()
|
6745
6950
|
else:
|
6746
6951
|
self.array = np.kron(self.array, np.ones((int(1/factor), int(1/factor)), dtype=self.array.dtype))
|
6747
6952
|
|
6748
|
-
self.mask_reset()
|
6749
|
-
|
6750
6953
|
self.count()
|
6751
6954
|
|
6955
|
+
# rebin must not change the type of the array
|
6956
|
+
assert self.array.dtype == self.dtype, _('Bad dtype')
|
6957
|
+
|
6752
6958
|
def read_txt_header(self):
|
6753
6959
|
"""
|
6754
6960
|
Read header from txt file
|
@@ -7940,26 +8146,85 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
7940
8146
|
|
7941
8147
|
def map_values(self, keys_vals:dict, default:float=None):
|
7942
8148
|
"""
|
7943
|
-
|
8149
|
+
Mapping array values to new values defined by a dictionnary.
|
8150
|
+
|
8151
|
+
First, check if all values are in keys_vals. If not, set to default.
|
8152
|
+
If default is None, set to nullvalue.
|
8153
|
+
|
8154
|
+
:param keys_vals: dictionary of values to map
|
8155
|
+
:param default: default value if key not found
|
7944
8156
|
"""
|
7945
8157
|
|
7946
8158
|
vals = self.get_unique_values()
|
7947
8159
|
|
7948
|
-
|
7949
|
-
self.array.data[:,:] = default
|
7950
|
-
|
8160
|
+
def_keys = []
|
7951
8161
|
for val in vals:
|
7952
8162
|
if val not in keys_vals:
|
7953
|
-
logging.warning(f"Value {val} not in keys_vals")
|
8163
|
+
logging.warning(_(f"Value {val} not in keys_vals -- Will be set to default or NullValue"))
|
8164
|
+
def_keys.append(val)
|
7954
8165
|
continue
|
7955
8166
|
|
7956
8167
|
for key, val in keys_vals.items():
|
7957
8168
|
self.array.data[self.array.data == key] = val
|
7958
8169
|
|
8170
|
+
if default is None:
|
8171
|
+
default = self.nullvalue
|
8172
|
+
|
8173
|
+
for key in def_keys:
|
8174
|
+
self.array.data[self.array.data == key] = default
|
8175
|
+
|
7959
8176
|
self.mask_data(self.nullvalue)
|
7960
8177
|
|
7961
8178
|
self.reset_plot()
|
7962
8179
|
|
8180
|
+
@classmethod
|
8181
|
+
def from_other_epsg_coo(cls,
|
8182
|
+
input_raster_path:str,
|
8183
|
+
input_srs='EPSG:3812',
|
8184
|
+
output_srs='EPSG:31370',
|
8185
|
+
resampling_method=gdal.GRA_Bilinear,
|
8186
|
+
xRes:float=0.5, yRes:float=0.5):
|
8187
|
+
"""
|
8188
|
+
Reprojects and resamples a raster file from an other EPSG coordinates and return it as a WolfArray.
|
8189
|
+
|
8190
|
+
:param input_raster_path: The path to the input raster file.
|
8191
|
+
:type input_raster_path: str
|
8192
|
+
:param input_srs: The input spatial reference system (SRS) in the format 'EPSG:XXXX'. Defaults to Lambert 2008 'EPSG:3812'.
|
8193
|
+
:type input_srs: str
|
8194
|
+
:param output_srs: The output spatial reference system (SRS) in the format 'EPSG:XXXX'. Defaults to Belgian Lambert 72 'EPSG:31370'.
|
8195
|
+
:type output_srs: str
|
8196
|
+
:param resampling_method: The resampling method to use. Defaults to gdal.GRA_Bilinear. Resampling method can be chosen among the gdal GRA_*
|
8197
|
+
constants (gdal.GRA_Average; gdal.GRA_Bilinear; gdal.GRA_Cubic; gdal.GRA_CubicSpline;
|
8198
|
+
gdal.GRA_Lanczos; gdal.GRA_Mode; gdal.GRA_NearestNeighbour)
|
8199
|
+
:type resampling_method: int
|
8200
|
+
:param xRes: The desired output resolution in the x direction. Defaults to 0.5.
|
8201
|
+
:type xRes (float): float
|
8202
|
+
:param yRes: The desired output resolution in the y direction. Defaults to 0.5.
|
8203
|
+
:type yRes (float): float
|
8204
|
+
|
8205
|
+
:raises AssertionError: If the input or output raster file is not a GeoTIFF file.
|
8206
|
+
:raises RuntimeError: If the input raster file cannot be opened.
|
8207
|
+
:raises PermissionError: If there is a permission error while trying to delete the output raster file.
|
8208
|
+
:raises Exception: If an unexpected error occurs while trying to delete the output raster file.
|
8209
|
+
:raises RuntimeError: If the reprojection fails for the input raster file.
|
8210
|
+
|
8211
|
+
:return: WolfArray
|
8212
|
+
"""
|
8213
|
+
|
8214
|
+
#sanitize input
|
8215
|
+
input_raster_path = str(input_raster_path)
|
8216
|
+
input_srs = str(input_srs)
|
8217
|
+
output_srs = str(output_srs)
|
8218
|
+
|
8219
|
+
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"
|
8220
|
+
|
8221
|
+
# Define temporary files
|
8222
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
8223
|
+
output_raster_path = os.path.join(temp_dir, "Array_72.tif")
|
8224
|
+
reproject_and_resample_raster(input_raster_path, output_raster_path, input_srs, output_srs, resampling_method, xRes, yRes)
|
8225
|
+
Array3 = WolfArray(output_raster_path, nullvalue=-9999)
|
8226
|
+
return Array3
|
8227
|
+
|
7963
8228
|
class WolfArrayMB(WolfArray):
|
7964
8229
|
"""
|
7965
8230
|
Matrice multiblocks
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: wolfhece
|
3
|
-
Version: 2.1.
|
3
|
+
Version: 2.1.48
|
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=t3U7YQwBA5OYh-Pf0tffZCv9Ha9SH3S-XAhFXVOpeBs,390808
|
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
|
@@ -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=cWkTaA4nY9I8-FLNlXBwn0xkvaN1EXw6M9NYUYnTqf8,368492
|
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=1j6FkD-S6lKIU8cwsITdvdCE6HZVOxDK9aVtSrdT5Vw,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
|
@@ -254,7 +255,7 @@ wolfhece/report/reporting.py,sha256=JUEXovx_S4jpYkJEBU0AC-1Qw2OkkWyV3VAp6iOfSHc,
|
|
254
255
|
wolfhece/report/wolf_report.png,sha256=NoSV58LSwb-oxCcZScRiJno-kxDwRdm_bK-fiMsKJdA,592485
|
255
256
|
wolfhece/scenario/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
256
257
|
wolfhece/scenario/check_scenario.py,sha256=w7_SST4n_uec-MUBK36gbJzz2KC8qT_bVJ_VNyp7cMo,4917
|
257
|
-
wolfhece/scenario/config_manager.py,sha256=
|
258
|
+
wolfhece/scenario/config_manager.py,sha256=UzInaAtxmTLqUaXAHg17iLcUZRGTrPPLsj2D9kBs6wI,85468
|
258
259
|
wolfhece/scenario/imposebc_void.py,sha256=PqA_99hKcaqK5zsK6IRIc5Exgg3WVpgWU8xpwNL49zQ,5571
|
259
260
|
wolfhece/scenario/update_void.py,sha256=ay8C_FxfXN627Hx46waaAO6F3ovYmOCTxseUumKAY7c,7474
|
260
261
|
wolfhece/shaders/fragment_shader_texture.glsl,sha256=w6h8d5mJqFaGbao0LGmjRcFFdcEQ3ICIl9JpuT71K5k,177
|
@@ -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.48.dist-info/METADATA,sha256=2S8MGX7bCP41sSY7a9scSmcsfKj2w8uiaMzIY5bIY9k,2548
|
282
|
+
wolfhece-2.1.48.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
283
|
+
wolfhece-2.1.48.dist-info/entry_points.txt,sha256=Q5JuIWV4odeIJI3qc6fV9MwRoz0ezqPVlFC1Ppm_vdQ,395
|
284
|
+
wolfhece-2.1.48.dist-info/top_level.txt,sha256=EfqZXMVCn7eILUzx9xsEu2oBbSo9liWPFWjIHik0iCI,9
|
285
|
+
wolfhece-2.1.48.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|