wolfhece 2.1.129__py3-none-any.whl → 2.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wolfhece/PyDraw.py +109 -46
- wolfhece/PyGui.py +3 -0
- wolfhece/PyGuiHydrology.py +24 -24
- wolfhece/PyPalette.py +27 -11
- wolfhece/Results2DGPU.py +17 -0
- wolfhece/acceptability/acceptability_gui.py +29 -18
- wolfhece/acceptability/func.py +23 -21
- wolfhece/apps/version.py +2 -2
- wolfhece/eikonal.py +1 -1
- wolfhece/hydrology/Catchment.py +2 -2
- wolfhece/hydrology/Comparison.py +26 -28
- wolfhece/hydrology/plot_hydrology.py +2 -2
- wolfhece/lagrangian/particle_system_ui.py +1 -1
- wolfhece/lagrangian/particles.py +1 -1
- wolfhece/lazviewer/processing/estimate_normals/estimate_normals.cp310-win_amd64.pyd +0 -0
- wolfhece/lazviewer/vfuncsdir/vfuncs.cp310-win_amd64.pyd +0 -0
- wolfhece/lazviewer/viewer/viewer.exe +0 -0
- wolfhece/lazviewer/viewer/viewer_np1_23_5.exe +0 -0
- wolfhece/libs/Wolf_tools.dll +0 -0
- wolfhece/libs/get_infos.cp310-win_amd64.pyd +0 -0
- wolfhece/libs/verify_wolf.cp310-win_amd64.pyd +0 -0
- wolfhece/libs/wolfogl.cp310-win_amd64.pyd +0 -0
- wolfhece/tools2d_dll.py +359 -0
- wolfhece/wolf_array.py +3 -2
- wolfhece/wolfresults_2D.py +162 -33
- {wolfhece-2.1.129.dist-info → wolfhece-2.2.1.dist-info}/METADATA +14 -9
- {wolfhece-2.1.129.dist-info → wolfhece-2.2.1.dist-info}/RECORD +30 -28
- wolfhece/libs/wolfpy.cp310-win_amd64.pyd +0 -0
- {wolfhece-2.1.129.dist-info → wolfhece-2.2.1.dist-info}/WHEEL +0 -0
- {wolfhece-2.1.129.dist-info → wolfhece-2.2.1.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.1.129.dist-info → wolfhece-2.2.1.dist-info}/top_level.txt +0 -0
wolfhece/acceptability/func.py
CHANGED
@@ -287,14 +287,14 @@ class Accept_Manager():
|
|
287
287
|
|
288
288
|
self.scenario:str = str(self._scenario)
|
289
289
|
|
290
|
-
|
290
|
+
|
291
291
|
self.IN_SA_BASE = self.IN_WATER_DEPTH / self.SA.stem / "Scenario_baseline"
|
292
292
|
self.IN_SA_BASE_INTERP = self.IN_SA_BASE / "INTERP_WD"
|
293
|
-
|
293
|
+
|
294
294
|
self.IN_SCEN_DIR = self.IN_WATER_DEPTH / self.SA.stem / self.scenario
|
295
295
|
self.IN_SA_INTERP = self.IN_SCEN_DIR / "INTERP_WD"
|
296
296
|
self.IN_SA_EXTRACTED = self.IN_SCEN_DIR / "EXTRACTED_LAST_STEP_WD"
|
297
|
-
self.IN_SA_DEM = self.IN_SCEN_DIR / "DEM_FILES"
|
297
|
+
self.IN_SA_DEM = self.IN_SCEN_DIR / "DEM_FILES"
|
298
298
|
self.IN_CH_SA_SC = self.IN_CH_VULN /self.SA.stem / self.scenario
|
299
299
|
self.IN_CH_SA_SC_MNT_VRT = self.IN_CH_SA_SC / "__MNT_assembly.vrt"
|
300
300
|
self.IN_CH_SA_SC_MNT_tif = self.IN_CH_SA_SC / "MNTassembly"
|
@@ -312,19 +312,19 @@ class Accept_Manager():
|
|
312
312
|
|
313
313
|
self.OUT_WITHVULN = self.OUT_SCEN_DIR / "vuln_ scenarios"
|
314
314
|
self.OUT_VULN_VRT = self.OUT_WITHVULN / "__vuln_assembly.vrt"
|
315
|
-
self.OUT_VULN_S = self.OUT_WITHVULN / "Vulnerability_scenarios"
|
315
|
+
self.OUT_VULN_S = self.OUT_WITHVULN / "Vulnerability_scenarios"
|
316
316
|
self.OUT_VULN_Stif = self.OUT_WITHVULN / "Vulnerability_scenarios.tif"
|
317
317
|
self.OUT_MASKED_RIVER_S = self.OUT_WITHVULN / "Masked_River_extent_scenarios.tiff"
|
318
318
|
self.OUT_ACCEPT_Stif = self.OUT_WITHVULN / "Acceptability_scenarios.tiff"
|
319
319
|
self.OUT_ACCEPT_RESAMP_Stif = self.OUT_WITHVULN / "Acceptability_scenarios_resampled.tiff"
|
320
|
-
|
320
|
+
|
321
321
|
self.OUT_BASELINE = self.OUT_SCEN_DIR / "baseline"
|
322
322
|
self.OUT_VULN = self.OUT_BASELINE / "Vulnerability_baseline.tiff"
|
323
323
|
self.OUT_CODE = self.OUT_BASELINE / "Vulnerability_Code_baseline.tiff"
|
324
324
|
self.OUT_MASKED_RIVER = self.OUT_BASELINE / "Masked_River_extent_baseline.tiff"
|
325
325
|
self.OUT_ACCEPT = self.OUT_BASELINE / "Acceptability_baseline.tiff"
|
326
326
|
self.OUT_ACCEPT_RESAMP = self.OUT_BASELINE / "Acceptability_baseline_resampled.tiff"
|
327
|
-
|
327
|
+
|
328
328
|
else:
|
329
329
|
self.scenario = None
|
330
330
|
|
@@ -472,7 +472,7 @@ class Accept_Manager():
|
|
472
472
|
sims = self.get_sims_files_for_scenario()
|
473
473
|
|
474
474
|
if len(sims)==0:
|
475
|
-
logging.info("No simulations found at this stage")
|
475
|
+
logging.info("No simulations found at this stage")
|
476
476
|
return None
|
477
477
|
|
478
478
|
if "_h.tif" in sims[0].name:
|
@@ -561,7 +561,7 @@ class Accept_Manager():
|
|
561
561
|
os.path.join(os.path.dirname(path), os.path.basename(path).replace("Q", "T"))
|
562
562
|
for path in sims
|
563
563
|
]
|
564
|
-
|
564
|
+
|
565
565
|
if len(sims)==0:
|
566
566
|
logging.info("No simulations found at this stage.")
|
567
567
|
return []
|
@@ -570,22 +570,22 @@ class Accept_Manager():
|
|
570
570
|
# searching for the position of the return period in the name
|
571
571
|
idx_T = [Path(cursim).name.find("T") for cursim in sims_modif]
|
572
572
|
idx_h = [Path(cursim).name.find(".tif") for cursim in sims_modif]
|
573
|
-
|
573
|
+
|
574
574
|
# create the list of return periods -- only the numeric part
|
575
575
|
sims = [int(Path(cursim).name[idx_T[i]+1:idx_h[i]]) for i, cursim in enumerate(sims_modif)]
|
576
576
|
return sorted(sims)
|
577
|
-
|
577
|
+
|
578
578
|
def get_modifiedrasters(self):
|
579
579
|
folder = Path(self.IN_CH_SA_SC)
|
580
580
|
vuln_tiff_files = [str(file.name) for file in folder.rglob("*.tiff") if file.name.startswith('vuln_')]
|
581
581
|
vuln_tif_files = [str(file.name)for file in folder.rglob("*.tif") if file.name.startswith('vuln_')]
|
582
|
-
vuln_files = vuln_tiff_files + vuln_tif_files
|
582
|
+
vuln_files = vuln_tiff_files + vuln_tif_files
|
583
583
|
|
584
584
|
folder = Path(self.IN_CH_SA_SC)
|
585
585
|
mnt_tiff_files = [str(file.name) for file in folder.rglob("*.tiff") if file.name.startswith('MNTmodifs_')]
|
586
586
|
mnt_tif_files = [str(file.name) for file in folder.rglob("*.tif") if file.name.startswith('MNTmodifs_')]
|
587
587
|
mnt_files = mnt_tiff_files + mnt_tif_files
|
588
|
-
|
588
|
+
|
589
589
|
return vuln_files + mnt_files
|
590
590
|
|
591
591
|
def get_ponderations(self) -> pd.DataFrame:
|
@@ -732,7 +732,7 @@ class Accept_Manager():
|
|
732
732
|
self.OUT_SCEN_DIR.mkdir(parents=True, exist_ok=True)
|
733
733
|
self.OUT_WITHVULN.mkdir(parents=True, exist_ok=True)
|
734
734
|
self.OUT_BASELINE.mkdir(parents=True, exist_ok=True)
|
735
|
-
|
735
|
+
|
736
736
|
|
737
737
|
return True
|
738
738
|
|
@@ -898,15 +898,15 @@ class Accept_Manager():
|
|
898
898
|
|
899
899
|
if len(code) == 0:
|
900
900
|
logging.error("The code rasters do not exist")
|
901
|
-
return
|
901
|
+
return ["The code rasters do not exist"]
|
902
902
|
|
903
903
|
if len(vuln) == 0:
|
904
904
|
logging.error("The vulnerability rasters do not exist")
|
905
|
-
return
|
905
|
+
return ["The vulnerability rasters do not exist"]
|
906
906
|
|
907
907
|
if len(code) != len(vuln):
|
908
908
|
logging.error("The number of code and vulnerability rasters do not match")
|
909
|
-
return
|
909
|
+
return ["The number of code and vulnerability rasters do not match"]
|
910
910
|
|
911
911
|
# we take a reference raster
|
912
912
|
ref = gdal.Open(str(code[0]))
|
@@ -1026,7 +1026,7 @@ class Accept_Manager():
|
|
1026
1026
|
dataset = None
|
1027
1027
|
|
1028
1028
|
logging.info("All the existing .tif files have been copied to the destination directory.")
|
1029
|
-
|
1029
|
+
|
1030
1030
|
def wich_river_trace(self):
|
1031
1031
|
""" Searches for existing riverbed traces: if none ending with '_scenarios' are found, it selects the baseline trace."""
|
1032
1032
|
trace = None
|
@@ -1037,8 +1037,8 @@ class Accept_Manager():
|
|
1037
1037
|
else :
|
1038
1038
|
logging.error("No Masked_River_extent files. Please provide them.")
|
1039
1039
|
return trace
|
1040
|
-
|
1041
|
-
|
1040
|
+
|
1041
|
+
|
1042
1042
|
|
1043
1043
|
|
1044
1044
|
def clip_layer(layer:str,
|
@@ -1503,7 +1503,7 @@ def match_vulnerability2sim(inRas:Path, outRas:Path, MODREC:Path):
|
|
1503
1503
|
:param MODREC: the MODREC/simulation extent file
|
1504
1504
|
|
1505
1505
|
"""
|
1506
|
-
|
1506
|
+
|
1507
1507
|
inRas = str(inRas)
|
1508
1508
|
outRas = str(outRas)
|
1509
1509
|
MODREC = str(MODREC)
|
@@ -1524,7 +1524,7 @@ def update_accept(accept, model_h, ij, bounds, loc_accept):
|
|
1524
1524
|
for idx in range(len(bounds)):
|
1525
1525
|
for i,j in ij:
|
1526
1526
|
#lit dans wd vs Ti où on est et associe son score d'accept
|
1527
|
-
if bounds[idx,0] < model_h[i,j] <= bounds[idx,1]:
|
1527
|
+
if bounds[idx,0] < model_h[i,j] <= bounds[idx,1]:
|
1528
1528
|
accept[i,j] = loc_accept[idx]
|
1529
1529
|
|
1530
1530
|
def compute_acceptability(manager:Accept_Manager,
|
@@ -1666,6 +1666,8 @@ def shp_to_raster(vector_fn:str | Path, raster_fn:str | Path, pixel_size:float =
|
|
1666
1666
|
layer = source_layer,
|
1667
1667
|
burn_values = [1],
|
1668
1668
|
options=["ALL_TOUCHED=TRUE"])
|
1669
|
+
|
1670
|
+
target_ds.FlushCache()
|
1669
1671
|
target_ds = None
|
1670
1672
|
vector_fn = raster_fn = None
|
1671
1673
|
|
wolfhece/apps/version.py
CHANGED
wolfhece/eikonal.py
CHANGED
@@ -78,7 +78,7 @@ def __solve_eikonal_with_data(sources:list[list[int,int]],
|
|
78
78
|
# store the fixed points
|
79
79
|
# - fix sources points
|
80
80
|
# - fix every first element of the heap after pop
|
81
|
-
fixed = np.zeros(speed.shape, dtype = np.
|
81
|
+
fixed = np.zeros(speed.shape, dtype = np.uint8)
|
82
82
|
|
83
83
|
# fix the border
|
84
84
|
fixed[:, 0] = True
|
wolfhece/hydrology/Catchment.py
CHANGED
@@ -33,8 +33,8 @@ else:
|
|
33
33
|
print(_('Note: do not forget to install the graphviz app and add it to the PATH to make it work'))
|
34
34
|
# --------------------------------
|
35
35
|
|
36
|
-
from ..wolf_texture import genericImagetexture
|
37
|
-
from ..PyDraw import WolfMapViewer
|
36
|
+
# from ..wolf_texture import genericImagetexture
|
37
|
+
# from ..PyDraw import WolfMapViewer
|
38
38
|
from .SubBasin import *
|
39
39
|
from .RetentionBasin import *
|
40
40
|
from .read import *
|
wolfhece/hydrology/Comparison.py
CHANGED
@@ -12,8 +12,6 @@ import sys # module to stop the program when an err
|
|
12
12
|
import os
|
13
13
|
import matplotlib.pyplot as plt
|
14
14
|
import numpy as np
|
15
|
-
from numpy.__config__ import show
|
16
|
-
from numpy.core.arrayprint import set_string_function
|
17
15
|
from wx.core import DD_CHANGE_DIR
|
18
16
|
|
19
17
|
from ..PyTranslate import _
|
@@ -587,7 +585,7 @@ class Comparison:
|
|
587
585
|
# print("ERROR: the simulation time is not long enough for this subbasin to be taken into account")
|
588
586
|
# sys.exit()
|
589
587
|
|
590
|
-
cur_module:RetentionBasin = curCatch.retentionBasinDict["J18"]
|
588
|
+
cur_module:RetentionBasin = curCatch.retentionBasinDict["J18"]
|
591
589
|
tmpHydro = cur_module.get_direct_insideRB_inlets(unit='m3/s')
|
592
590
|
|
593
591
|
y1.append(tmpHydro[:])
|
@@ -604,7 +602,7 @@ class Comparison:
|
|
604
602
|
# else:
|
605
603
|
# print("ERROR: the simulation time is not long enough for this subbasin to be taken into account")
|
606
604
|
# sys.exit()
|
607
|
-
cur_module:RetentionBasin = curCatch.retentionBasinDict["J18"]
|
605
|
+
cur_module:RetentionBasin = curCatch.retentionBasinDict["J18"]
|
608
606
|
tmpHydro = cur_module.get_direct_insideRB_inlets(unit='m3/s')
|
609
607
|
|
610
608
|
y1.append(tmpHydro[:])
|
@@ -1412,13 +1410,13 @@ class Comparison:
|
|
1412
1410
|
# graph_title = curCatch.name + " :"
|
1413
1411
|
# cur_t, curVol = curCatch.get_all_cumulRain(selection_by_iD)
|
1414
1412
|
|
1415
|
-
# for
|
1413
|
+
# for
|
1416
1414
|
# plt.figure()
|
1417
1415
|
# plt.title(graph_title)
|
1418
1416
|
# for i in range(len(curVol)):
|
1419
1417
|
# plt.plot(cur_t, curVol[i])
|
1420
1418
|
# plt.savefig(os.path.join(writeDir, graph_title))
|
1421
|
-
|
1419
|
+
|
1422
1420
|
# if show : plt.show()
|
1423
1421
|
|
1424
1422
|
|
@@ -1582,34 +1580,34 @@ class Comparison:
|
|
1582
1580
|
del self.plotDict[stationKey]["Add Data"]
|
1583
1581
|
|
1584
1582
|
|
1585
|
-
|
1583
|
+
|
1586
1584
|
def plot_Nash_and_peak(self, stationKey:list[str, int], measures:list[SubBasin], intervals:list=[], toShow:bool=True):
|
1587
1585
|
assert len(stationKey) == len(measures)
|
1588
1586
|
|
1589
|
-
all_ns = {stationKey[i]: [ self.myCatchments[el]["Object"].get_sub_Nash(measures[i], stationKey[i], intervals)
|
1590
|
-
for el in self.myCatchments ]
|
1587
|
+
all_ns = {stationKey[i]: [ self.myCatchments[el]["Object"].get_sub_Nash(measures[i], stationKey[i], intervals)
|
1588
|
+
for el in self.myCatchments ]
|
1591
1589
|
for i in range(len(stationKey))
|
1592
1590
|
}
|
1593
1591
|
print(all_ns)
|
1594
1592
|
|
1595
|
-
all_peaks = [ [ self.myCatchments[el]["Object"].get_sub_peak(stationKey[i], intervals)
|
1596
|
-
for el in self.myCatchments ]
|
1597
|
-
for i in range(len(stationKey))
|
1593
|
+
all_peaks = [ [ self.myCatchments[el]["Object"].get_sub_peak(stationKey[i], intervals)
|
1594
|
+
for el in self.myCatchments ]
|
1595
|
+
for i in range(len(stationKey))
|
1598
1596
|
]
|
1599
|
-
|
1597
|
+
|
1600
1598
|
print(all_peaks)
|
1601
1599
|
|
1602
|
-
meas_peak = [ measures[i].get_peak(intervals)
|
1600
|
+
meas_peak = [ measures[i].get_peak(intervals)
|
1603
1601
|
for i in range(len(stationKey)) ]
|
1604
|
-
|
1602
|
+
|
1605
1603
|
# The following lines is take the peak difference between simulation and measurements -> Display 0.0 if the measurement is 0.0
|
1606
1604
|
isZero = np.array(meas_peak)==0
|
1607
1605
|
notZero = np.array(meas_peak)!=0
|
1608
|
-
peak_prop = {stationKey[i]: [ list( (np.array(el)-np.array(meas_peak[i]))/(np.array(meas_peak[i])+isZero[i]) *notZero[i] )
|
1609
|
-
for el in all_peaks[i] ]
|
1606
|
+
peak_prop = {stationKey[i]: [ list( (np.array(el)-np.array(meas_peak[i]))/(np.array(meas_peak[i])+isZero[i]) *notZero[i] )
|
1607
|
+
for el in all_peaks[i] ]
|
1610
1608
|
for i in range(len(stationKey))
|
1611
1609
|
}
|
1612
|
-
|
1610
|
+
|
1613
1611
|
print(meas_peak)
|
1614
1612
|
print(peak_prop)
|
1615
1613
|
|
@@ -1637,7 +1635,7 @@ class Comparison:
|
|
1637
1635
|
continue
|
1638
1636
|
else:
|
1639
1637
|
colors_Nash[key][i_model].append("g")
|
1640
|
-
|
1638
|
+
|
1641
1639
|
|
1642
1640
|
colors_peaks = {}
|
1643
1641
|
for key, value in peak_prop.items():
|
@@ -1660,15 +1658,15 @@ class Comparison:
|
|
1660
1658
|
all_names = ["\n - \n".join([cdate[0].strftime("%d/%m/%Y"), cdate[1].strftime("%d/%m/%Y")]) for cdate in intervals]
|
1661
1659
|
|
1662
1660
|
|
1663
|
-
## Plot
|
1661
|
+
## Plot
|
1664
1662
|
nb_stations = len(stationKey)
|
1665
1663
|
type_of_model = [self.myCatchments[el]["Title"] for el in self.myCatchments]
|
1666
1664
|
type_of_data = ["Nash", r"$ \frac{Q^{s}_{max}-Q^{m}_{max}}{Q^{m}_{max}} $ "]
|
1667
1665
|
type_of_data_names = ["Nash", "Exceedance"]
|
1668
1666
|
|
1669
|
-
# ph.bar_Nash_n_other(all_data, all_colors, nb_x=len(intervals), nb_data=len(type_of_model), nb_lines=nb_stations,
|
1667
|
+
# ph.bar_Nash_n_other(all_data, all_colors, nb_x=len(intervals), nb_data=len(type_of_model), nb_lines=nb_stations,
|
1670
1668
|
# y_titles=type_of_data, x_titles=all_names, nameModel=type_of_model, line_names=sorted_keys, toShow=False)
|
1671
|
-
|
1669
|
+
|
1672
1670
|
# =========
|
1673
1671
|
# =========
|
1674
1672
|
# Plot tables - 2nd version with the table instead of bars
|
@@ -1680,12 +1678,12 @@ class Comparison:
|
|
1680
1678
|
all_peaks = {cur_catch["Title"]: np.array([cur_catch["Object"].get_sub_peak(stationKey[i], intervals) for i in range(len(stationKey))])
|
1681
1679
|
for cur_catch in self.myCatchments.values()
|
1682
1680
|
}
|
1683
|
-
|
1681
|
+
|
1684
1682
|
print(all_peaks)
|
1685
1683
|
|
1686
|
-
meas_peak = np.array([ measures[i].get_peak(intervals)
|
1684
|
+
meas_peak = np.array([ measures[i].get_peak(intervals)
|
1687
1685
|
for i in range(len(stationKey)) ])
|
1688
|
-
|
1686
|
+
|
1689
1687
|
# The following lines is take the peak difference between simulation and measurements -> Display 0.0 if the measurement is 0.0
|
1690
1688
|
isZero = (meas_peak==0)
|
1691
1689
|
notZero = (meas_peak!=0)
|
@@ -1696,13 +1694,13 @@ class Comparison:
|
|
1696
1694
|
|
1697
1695
|
# Concatenate all data
|
1698
1696
|
all_data = [all_ns, peak_prop]
|
1699
|
-
|
1697
|
+
|
1700
1698
|
for data, name_of_data in zip(all_data, type_of_data_names):
|
1701
1699
|
for cur_model, cur_data in data.items():
|
1702
1700
|
file_name = os.path.join(self.workingDir, name_of_data+"_"+cur_model)+".png"
|
1703
1701
|
# cur_title = cur_model + ": " + name_of_data
|
1704
|
-
ph.table_Nash_n_other(cur_data, name_of_data,
|
1705
|
-
row_names=sorted_keys, column_names=all_names,
|
1702
|
+
ph.table_Nash_n_other(cur_data, name_of_data,
|
1703
|
+
row_names=sorted_keys, column_names=all_names,
|
1706
1704
|
writeFile=file_name, toShow=False)
|
1707
1705
|
if toShow:
|
1708
1706
|
plt.show()
|
@@ -17,9 +17,9 @@ import math
|
|
17
17
|
import datetime
|
18
18
|
import sys
|
19
19
|
import logging
|
20
|
-
from numpy.core.arrayprint import set_string_function
|
20
|
+
# from numpy.core.arrayprint import set_string_function
|
21
21
|
|
22
|
-
from numpy.core.defchararray import index
|
22
|
+
# from numpy.core.defchararray import index
|
23
23
|
|
24
24
|
from ..PyTranslate import _
|
25
25
|
|
@@ -397,7 +397,7 @@ class Particle_system_to_draw(Element_To_Draw):
|
|
397
397
|
self._ps.nbx, self._ps.nby = value.array.shape
|
398
398
|
self._ps.dx, self._ps.dy = value.dx, value.dy
|
399
399
|
else:
|
400
|
-
assert value.dtype == np.
|
400
|
+
assert value.dtype == np.bool, 'Domain must be boolean'
|
401
401
|
self._ps.domain = value
|
402
402
|
self._ps.nbx, self._ps.nby = value.shape
|
403
403
|
|
wolfhece/lagrangian/particles.py
CHANGED
@@ -38,7 +38,7 @@ class Particles():
|
|
38
38
|
|
39
39
|
self.start_position = [x0, y0]
|
40
40
|
self.end_position = [x0.copy(), y0.copy()] # copy to define new memory storage
|
41
|
-
self._is_alive = np.ones_like(x0, dtype=np.
|
41
|
+
self._is_alive = np.ones_like(x0, dtype=np.bool)
|
42
42
|
|
43
43
|
def copy_prop_from(self, other:'Particles') -> None:
|
44
44
|
"""
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|