Analyse d’une matrice sur base de polygones et buffer

Import des modules

[ ]:
# import _add_path # for debugging purposes only - can be removed in production

try:
    from wolfhece import is_enough
    if not is_enough('2.2.31'):
        raise ImportError("Please update wolfhece to at least version 2.2.31")
except ImportError:
    raise ImportError("Please install the required version of wolfhece: pip install wolfhece>=2.2.30")

from wolfhece.analyze_poly import Array_analysis_polygons, Array_analysis_onepolygon
from wolfhece.wolf_array import WolfArray, header_wolf
from wolfhece.PyVertexvectors import vector, zone, Zones, wolfvertex as wv

import matplotlib.pyplot as plt
import numpy as np

Création d’une matrice de variables aléatoires

[2]:
h = header_wolf()
h.set_origin(25, 55) # Set the origin (lower-left) of the array
h.set_resolution(0.5 , 0.5) # Set the resolution of the array
h.shape = (1000, 2000) # Set the shape of the array (cells along x and y axes)

a = WolfArray(srcheader= h)

a.array[:,:] = np.random.rand(1000, 2000) * 10
a.mask_lower(5.)
a.set_nullvalue_in_mask()

a.plot_matplotlib(with_legend= True)
print("Number of values in the array:", a.nbnotnull)
Number of values in the array: 999532
../_images/tutorials_analyze_polygons_wbuffer_4_1.png

Création de polygones d’analyse

Pour l’exemple, on va définir deux polygones.

[3]:
# Create polygons
zone_poly = zone(name = 'polygons')

poly1 = vector(name=f'Polygon_1', parentzone=zone_poly)
poly1.add_vertices_from_array(np.array([[60, 100],
                                        [400, 350],
                                        [500, 270],
                                        [50, 75]]))
poly1.force_to_close()  # Ensure the polygon is closed

poly2 = vector(name=f'Polygon_2', parentzone=zone_poly)
poly2.add_vertices_from_array(np.array([[410, 650],
                                        [175, 900],
                                        [200, 600],
                                        [100, 600],
                                        [300, 500]]))
poly2.force_to_close()  # Ensure the polygon is closed

zone_poly.add_vector(poly1)
zone_poly.add_vector(poly2)

fig, ax = plt.subplots(figsize=(10, 10))
a.plot_matplotlib(figax = (fig, ax))
zone_poly.plot_matplotlib(ax)
ax.set_aspect('equal')
../_images/tutorials_analyze_polygons_wbuffer_6_0.png

Création de l’objet d’analyse avec buffer

Il est possible de définir un buffer autour des polygones. Le buffer est une zone supplémentaire qui permet d’inclure des valeurs adjacentes aux polygones dans l’analyse.

Si un buffer est défini, le polygone sera une copie du polygone original avec un buffer de la taille définie. Autrement, le polygone est un pointeur vers le polygone original.

[4]:
analyze = Array_analysis_polygons(a, zone_poly, buffer_size= 50.)
[5]:
fig, ax = plt.subplots(figsize=(10, 10))
a.plot_matplotlib(figax = (fig, ax))
analyze.polygons.plot_matplotlib(ax)
ax.set_aspect('equal')
../_images/tutorials_analyze_polygons_wbuffer_9_0.png

Analyse d’un polygone spécifique

Il est possible de générer un graphique pour chaque polygone.

Au besoin, les clés des polygones peuvent être récupérées avec la propriété keys.

[6]:
analyze.keys
[6]:
['Polygon_1', 'Polygon_2']
[7]:
all_plots = analyze['Polygon_1'].plot_values()
all_plots = analyze['Polygon_2'].plot_values()
../_images/tutorials_analyze_polygons_wbuffer_12_0.png
../_images/tutorials_analyze_polygons_wbuffer_12_1.png
[8]:
print('Volume Poly1 : ', analyze['Polygon_1'].values('Volume'))
print('Volume Poly2 : ', analyze['Polygon_2'].values('Volume'))
Volume Poly1 :  325365.2
Volume Poly2 :  431380.8

Récupération des coordonnées des mailles dans un polygone

et ensuite des valeurs sur base de ces coordonnées.

[9]:
analyze['Polygon_1'].select_cells(mode = 'polygon')
print('Number of cells in Polygon_1:', analyze['Polygon_1'].n_selected_cells)

# get values "manually"
values = [a.get_value(x, y, convert_to_float=False) for x,y in analyze['Polygon_1'].get_selection()]
print('Values in Polygon_1:', values[:10]) # just print first 10 values
Number of cells in Polygon_1: 173679
Values in Polygon_1: [np.float32(6.318269), np.float32(7.2763643), np.float32(7.772545), np.float32(6.8120513), np.float32(7.3207436), np.float32(5.691848), np.float32(7.083117), np.float32(9.185118), np.float32(8.112824), np.float32(8.33562)]

Masquer une portion de matrice sur base d’un vecteur

  • Définir un vecteur central

  • Utiliser des parallèles pour définir un polygone

  • Masquer les valeurs de la matrice qui sont à l’intérieur du polygone

[10]:
river = vector(name='River')
river.add_vertices_from_array(np.array([[100, 100],
                                         [400, 200],
                                         [400, 800],
                                         [200, 700],
                                         [300, 1000]]))

left = river.parallel_offset(25., side='left')
right = river.parallel_offset(25., side='right')
right.reverse()  # Reverse the right side to close the polygon correctly
river_poly = left + right
river_poly.force_to_close()  # Ensure the polygon is closed

a.mask_insidepoly(river_poly)

fig, ax = a.plot_matplotlib()
river_poly.plot_matplotlib(ax)
poly1.plot_matplotlib(ax)
poly2.plot_matplotlib(ax)
../_images/tutorials_analyze_polygons_wbuffer_17_0.png
[11]:
analyze.update_values()
all_plots = analyze['Polygon_1'].plot_values()
all_plots = analyze['Polygon_2'].plot_values()

analyze['Polygon_1'].select_cells(mode = 'polygon')
print('Number of cells in Polygon_1:', analyze['Polygon_1'].n_selected_cells)
../_images/tutorials_analyze_polygons_wbuffer_18_0.png
../_images/tutorials_analyze_polygons_wbuffer_18_1.png
Number of cells in Polygon_1: 121939

Extraire d’autres grandeurs

Pour chaque polygone, il est calculé :

  • la moyenne des valeurs (opérateur Mean)

  • l’écart-type des valeurs (opérateur Std)

  • la médiane des valeurs (opérateur Median)

  • la somme des valeurs (opérateur Sum)

  • le “volumme” des valeurs (somme des valeurs multipliée par la surface du polygone) (opérateur Volume)

Il est toutefois possible de calculer d’autres grandeurs en exploitant la série de valeurs disponibles dans l’objet d’analyse via ‘values(‘Values’) qui retourne un DataFrame pandas.

[12]:
df = analyze['Polygon_1'].values('Values')
print('Type of returned object:', type(df))

print('Moyenne : ', df.mean())
print('Médiane : ', df.median())
print('Quantile 25 : ', df.quantile(0.25))
print('Quantile 75 : ', df.quantile(0.75))
print('Minimum : ', df.min())
print('Maximum : ', df.max())

df.hist(bins=20, density=True)
Type of returned object: <class 'pandas.core.frame.DataFrame'>
Moyenne :  Polygon_1    7.492949
dtype: float32
Médiane :  Polygon_1    7.48455
dtype: float32
Quantile 25 :  Polygon_1    6.239945
Name: 0.25, dtype: float32
Quantile 75 :  Polygon_1    8.743149
Name: 0.75, dtype: float32
Minimum :  Polygon_1    5.000029
dtype: float32
Maximum :  Polygon_1    9.999971
dtype: float32
[12]:
array([[<Axes: title={'center': 'Polygon_1'}>]], dtype=object)
../_images/tutorials_analyze_polygons_wbuffer_20_2.png