Skip to content

Visualize Module

plot_2d(points, x_dim='X', y_dim='Z', color_map='viridis', alpha=1.0, point_size=1, fig_size=None)

Plots a 2D scatter plot from a set of points with customizable dimensions, colors, and sizes.

:param points: A DataFrame containing point data with dimensions and 'HeightAboveGround'. :type points: pandas.DataFrame :param x_dim: The dimension for the X-axis ('X', 'Y', 'Z', or 'HeightAboveGround'). :type x_dim: str :param y_dim: The dimension for the Y-axis ('X', 'Y', 'Z', or 'HeightAboveGround'). :type y_dim: str :param color_map: The colormap used to color the points according to 'HeightAboveGround'. :type color_map: str :param alpha: The transparency level of the points. :type alpha: float :param point_size: The size of each point in the scatter plot. :type point_size: float :param fig_size: The size of the figure as a tuple (width, height). If None, it is computed based on the aspect ratio. :type fig_size: tuple or None :return: None :rtype: None :raises ValueError: If the provided dimensions are not valid.

Source code in pyforestscan/visualize.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
def plot_2d(points, x_dim='X', y_dim='Z', color_map='viridis', alpha=1.0, point_size=1, fig_size=None):
    """
    Plots a 2D scatter plot from a set of points with customizable dimensions, colors, and sizes.

    :param points: A DataFrame containing point data with dimensions and 'HeightAboveGround'.
    :type points: pandas.DataFrame
    :param x_dim: The dimension for the X-axis ('X', 'Y', 'Z', or 'HeightAboveGround').
    :type x_dim: str
    :param y_dim: The dimension for the Y-axis ('X', 'Y', 'Z', or 'HeightAboveGround').
    :type y_dim: str
    :param color_map: The colormap used to color the points according to 'HeightAboveGround'.
    :type color_map: str
    :param alpha: The transparency level of the points.
    :type alpha: float
    :param point_size: The size of each point in the scatter plot.
    :type point_size: float
    :param fig_size: The size of the figure as a tuple (width, height). If None, it is computed based on the aspect ratio.
    :type fig_size: tuple or None
    :return: None
    :rtype: None
    :raises ValueError: If the provided dimensions are not valid.
    """
    valid_dims = ['X', 'Y', 'Z', 'HeightAboveGround']
    if x_dim not in valid_dims or y_dim not in valid_dims:
        raise ValueError(f"Invalid dimensions. Choose from: {valid_dims}")

    x = points[x_dim]
    y = points[y_dim]
    colors = points['HeightAboveGround']

    if fig_size is None:
        aspect_ratio = (np.max(x) - np.min(x)) / (np.max(y) - np.min(y))
        fig_size = (10 * aspect_ratio, 10)

        max_fig_size = 20  # inches
        if max(fig_size) > max_fig_size:
            scale_factor = max_fig_size / max(fig_size)
            fig_size = (fig_size[0] * scale_factor, fig_size[1] * scale_factor)

    plt.figure(figsize=fig_size)

    plt.scatter(x, y, c=colors, cmap=color_map, alpha=alpha, s=point_size)
    plt.xlabel(x_dim)
    plt.ylabel(y_dim)
    plt.title(f'{x_dim} vs {y_dim} Colored by Height Above Ground')
    plt.colorbar(label='Height Above Ground (m)')
    plt.show()

plot_metric(title, metric, extent, metric_name=None, cmap='viridis', fig_size=None)

Plots a given metric using the provided data and configuration.

:param title: string The name of the metric to be plotted :param metric: ndarray 2D array representing the metric's values. :param extent: list List of four elements [xmin, xmax, ymin, ymax] defining the extent of the plot. :param metric_name: string, optional Label to be used for the colorbar. If None, the title is used as the metric name. This is useful for specifying units or a more detailed description of the metric. :param cmap: str, optional Colormap to be used for the plot. Default is 'viridis'. :param fig_size: tuple, optional Tuple specifying the size of the figure (width, height). Default is calculated based on the extent. :return: None :rtype: None

Source code in pyforestscan/visualize.py
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
def plot_metric(title, metric, extent, metric_name=None, cmap='viridis', fig_size=None):
    """
    Plots a given metric using the provided data and configuration.

    :param title: string
        The name of the metric to be plotted
    :param metric: ndarray
        2D array representing the metric's values.
    :param extent: list
        List of four elements [xmin, xmax, ymin, ymax] defining the extent of the plot.
    :param metric_name: string, optional
        Label to be used for the colorbar. If None, the title is used as the
        metric name. This is useful for specifying units or a more detailed
        description of the metric.
    :param cmap: str, optional
        Colormap to be used for the plot. Default is 'viridis'.
    :param fig_size: tuple, optional
        Tuple specifying the size of the figure (width, height). Default is calculated based on the extent.
    :return: None
    :rtype: None
    """
    if metric_name is None:
        metric_name = title
    if fig_size is None:
        x_range = extent[1] - extent[0]
        y_range = extent[3] - extent[2]
        aspect_ratio = x_range / y_range
        fig_size = (10 * aspect_ratio, 10)

        max_fig_size = 20
        if max(fig_size) > max_fig_size:
            scale_factor = max_fig_size / max(fig_size)
            fig_size = (fig_size[0] * scale_factor, fig_size[1] * scale_factor)

    plt.figure(figsize=fig_size)

    plt.imshow(metric.T, extent=extent, cmap=cmap)
    plt.colorbar(label=metric_name)
    plt.title(title)
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.show()

plot_pad(pad, slice_index, axis='x', cmap='viridis', hag_values=None, horizontal_values=None)

Plots a 2D slice of Plant Area Density (PAD) data with dZ HAG on the Y-axis.

:param pad: numpy.ndarray The 3D Plant Area Density data with shape (X, Y, HAG). :param slice_index: int The index of the slice to be plotted along the specified axis. :param axis: str, optional The axis along which to slice the data. Default is 'x'. Choose from 'x', 'y'. :param cmap: str, optional The colormap to be used for plotting. Default is 'viridis'. :param hag_values: numpy.ndarray, optional Array of HAG (Height Above Ground) values corresponding to the third dimension. If None, will use indices. :param horizontal_values: numpy.ndarray, optional Array of horizontal (X or Y) values corresponding to the first or second dimension. If None, will use indices. :raises ValueError: If an invalid axis is provided or slice_index is out of bounds. :return: None :rtype: None

Source code in pyforestscan/visualize.py
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
def plot_pad(pad, slice_index, axis='x', cmap='viridis', hag_values=None, horizontal_values=None):
    """
    Plots a 2D slice of Plant Area Density (PAD) data with dZ HAG on the Y-axis.

    :param pad: numpy.ndarray
        The 3D Plant Area Density data with shape (X, Y, HAG).
    :param slice_index: int
        The index of the slice to be plotted along the specified axis.
    :param axis: str, optional
        The axis along which to slice the data. Default is 'x'. Choose from 'x', 'y'.
    :param cmap: str, optional
        The colormap to be used for plotting. Default is 'viridis'.
    :param hag_values: numpy.ndarray, optional
        Array of HAG (Height Above Ground) values corresponding to the third dimension.
        If None, will use indices.
    :param horizontal_values: numpy.ndarray, optional
        Array of horizontal (X or Y) values corresponding to the first or second dimension.
        If None, will use indices.
    :raises ValueError: If an invalid axis is provided or slice_index is out of bounds.
    :return: None
    :rtype: None
    """
    # Validate the axis parameter
    if axis not in ['x', 'y']:
        raise ValueError(f"Invalid axis: '{axis}'. Choose from 'x' or 'y'.")

    if axis == 'x':
        if slice_index < 0 or slice_index >= pad.shape[0]:
            raise ValueError(f"slice_index {slice_index} out of range for axis 'x' with size {pad.shape[0]}")
        pad_2d = pad[slice_index, :, :]
        horizontal_axis_label = 'Y'
        horizontal_axis_values = horizontal_values if horizontal_values is not None else np.arange(pad.shape[1])
    else:  # axis == 'y'
        if slice_index < 0 or slice_index >= pad.shape[1]:
            raise ValueError(f"slice_index {slice_index} out of range for axis 'y' with size {pad.shape[1]}")
        pad_2d = pad[:, slice_index, :]
        horizontal_axis_label = 'X'
        horizontal_axis_values = horizontal_values if horizontal_values is not None else np.arange(pad.shape[0])

    hag_values = hag_values if hag_values is not None else np.arange(pad.shape[2])

    pad_2d = pad_2d.T

    if horizontal_values is not None:
        if axis == 'x' and len(horizontal_values) != pad.shape[1]:
            raise ValueError("Length of horizontal_values does not match the Y dimension of pad.")
        if axis == 'y' and len(horizontal_values) != pad.shape[0]:
            raise ValueError("Length of horizontal_values does not match the X dimension of pad.")
    else:
        horizontal_axis_values = np.arange(pad.shape[1]) if axis == 'x' else np.arange(pad.shape[0])

    plt.figure(figsize=(10, 6))
    img = plt.imshow(
        pad_2d,
        cmap=cmap,
        origin='lower',
        extent=(
            horizontal_axis_values.min(),
            horizontal_axis_values.max(),
            hag_values.min(),
            hag_values.max()
        ),
        aspect='auto'
    )
    plt.colorbar(img, label='PAD')
    plt.title(f'Plant Area Density (PAD) - {horizontal_axis_label} vs dZ at Slice {slice_index}')
    plt.xlabel(horizontal_axis_label)
    plt.ylabel('dZ')
    plt.tight_layout()
    plt.show()