Skip to content

plotting

Helpers for plotting roughness tables and arrays.

dem_imshow(dem, xmin=None, xmax=None, ymin=None, ymax=None, band='slope', ax=None, title='', cmap='viridis', **kwargs)

Use imshow to display a stacked DEM image (slope, azimuth, elevation).

Parameters:

Name Type Description Default
dem ndarray

A 3D stacked DEM (slope, azimuth, elevation).

required
xmin, xmax, ymin, ymax (int

The x and y index ranges to plot.

required
band str or tuple

The band to display. Valid values are 'slope', 'azim', 'elev', or a tuple of (0, 1, 2) respectively.

'slope'
ax Axes

Axes to plot on. If not provided, a new Axes object will be generated.

None
title str

Plot title (default: '')

''
cmap str

Colormap (default: "gray").

'viridis'
Source code in roughness/plotting.py
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
def dem_imshow(
    dem,
    xmin=None,
    xmax=None,
    ymin=None,
    ymax=None,
    band="slope",
    ax=None,
    title="",
    cmap="viridis",
    **kwargs,
):
    """
    Use imshow to display a stacked DEM image (slope, azimuth, elevation).

    Parameters:
        dem (ndarray): A 3D stacked DEM (slope, azimuth, elevation).
        xmin, xmax, ymin, ymax (int): The x and y index ranges to plot.
        band (str or tuple): The band to display. Valid values are 'slope', 
            'azim', 'elev', or a tuple of (0, 1, 2) respectively.
        ax (matplotlib.axes.Axes, optional): Axes to plot on. If not provided, 
            a new Axes object will be generated.
        title (str, optional): Plot title (default: '')
        cmap (str, optional): Colormap (default: "gray").
    """
    zmap = {"slope": 0, "azim": 1, "elev": 2, 0: "slope", 1: "azim", 2: "elev"}
    if len(dem.shape) > 2 and dem.shape[2] > 1:
        if isinstance(band, str) and band in zmap:
            zind = zmap[band]
        elif isinstance(band, int) and band in (0, 1, 2):
            zind = band
        else:
            raise ValueError(f"Unknown band {band} specified.")
        if title is None:
            title = f"DEM {zmap[zind]}"
    else:
        zind = None
    if ax is None:
        _, ax = plt.subplots()
    p = ax.imshow(dem[xmin:xmax, ymin:ymax, zind].T, cmap=cmap, **kwargs)
    ax.set_title(title)
    return p

m3_imshow(img, xmin=None, xmax=None, ymin=None, ymax=None, wl=750, ax=None, title=None, cmap='gray', **kwargs)

Use imshow to display an M3 image. Specify wavelength, wl, to show the closest channel to that wavelength.

Parameters:

Name Type Description Default
img ndarray

M3 image.

required
xmin, xmax, ymin, ymax (int

The x and y index ranges to plot.

required
wl int

Wavelength to show, gets nearest (default: 750nm).

750
ax Axes

Axes to plot on. If not provided, a new Axes object will be generated.

None
title str

Plot title (default: '')

None
cmap str

Colormap (default: "gray").

'gray'
Source code in roughness/plotting.py
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
def m3_imshow(
    img,
    xmin=None,
    xmax=None,
    ymin=None,
    ymax=None,
    wl=750,
    ax=None,
    title=None,
    cmap="gray",
    **kwargs,
):
    """
    Use imshow to display an M3 image. Specify wavelength, wl, to show the
    closest channel to that wavelength.

    Parameters:
        img (ndarray): M3 image.
        xmin, xmax, ymin, ymax (int): The x and y index ranges to plot.
        wl (int, optional): Wavelength to show, gets nearest (default: 750nm).
        ax (matplotlib.axes.Axes, optional): Axes to plot on. If not provided, 
            a new Axes object will be generated.
        title (str, optional): Plot title (default: '')
        cmap (str, optional): Colormap (default: "gray").
    """
    band = 0 if len(img.shape) > 2 else None
    if ax is None:
        _, ax = plt.subplots()
    if len(img.shape) > 2 and img.shape[2] > 1:
        band, wl = m3.m3_wl_to_ind(wl, img)
        if title is None:
            title = f"M3 img: band {band+1} ({wl} nm)"
    p = ax.imshow(img[xmin:xmax, ymin:ymax, band].T, cmap=cmap, **kwargs)
    ax.set_title(title)
    return p

m3_spec(img, fmt='-', wls=None, ax=None, title=None, **kwargs)

Plot M3 spectrum.

Parameters:

Name Type Description Default
img ndarray

M3 image.

required
fmt str

Plot format (default: '-' for line).

'-'
wls ndarray

Wavelengths to plot (default: all).

None
ax Axes

Axes to plot on. If not provided, a new Axes object will be generated.

None
title str

Plot title (default: '')

None
Source code in roughness/plotting.py
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
def m3_spec(img, fmt="-", wls=None, ax=None, title=None, **kwargs):
    """
    Plot M3 spectrum.

    Parameters:
        img (ndarray): M3 image.
        fmt (str, optional): Plot format (default: '-' for line).
        wls (ndarray, optional): Wavelengths to plot (default: all).
        ax (matplotlib.axes.Axes, optional): Axes to plot on. If not provided, 
            a new Axes object will be generated.
        title (str, optional): Plot title (default: '')
    """
    if title is None:
        title = "M3 spectrum"
    if ax is None:
        _, ax = plt.subplots()
    if len(img.shape) > 2 and img.shape[2] > 1:
        m3wls, spec = m3.get_avg_spec(img, wls=wls)
    else:
        m3wls, spec = m3.get_spec(img, wls=wls)
    if wls is None:
        wls = m3wls
    ax.plot(wls, spec, fmt, **kwargs)
    ax.set_title(title)
    ax.set_xlabel("Wavelength [microns]")
    return ax

plot_slope_az_table(table, cmap_r=False, clabel=None, title=None, ax=None, proj=None, vmin=None, vmax=None, extent=None, **kwargs)

Plot a 2D line-of-sight table with facet slope vs facet azimuth.

Parameters:

Name Type Description Default
table ndarray

A 2D array of slope vs azimuth.

required
cmap_r bool

Use a reverse colormap. Default is False.

False
clabel str

Label for the colorbar. Default is an empty string.

None
ax Axes

Axes to plot on. If not provided, a new Axes object will be generated.

None
proj str

The projection to use. Valid values are 'polar' and None. Default is None.

None
vmin float

The minimum value for the colorbar. Default is None.

None
vmax float

The maximum value for the colorbar. Default is None.

None
Source code in roughness/plotting.py
 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
 52
 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
 95
 96
 97
 98
 99
100
101
102
103
104
105
def plot_slope_az_table(
    table,
    cmap_r=False,
    clabel=None,
    title=None,
    ax=None,
    proj=None,
    vmin=None,
    vmax=None,
    extent=None,
    **kwargs,
):
    """
    Plot a 2D line-of-sight table with facet slope vs facet azimuth.

    Parameters:
        table (ndarray): A 2D array of slope vs azimuth.
        cmap_r (bool, optional): Use a reverse colormap. Default is False.
        clabel (str, optional): Label for the colorbar. Default is an empty
            string.
        ax (matplotlib.axes.Axes, optional): Axes to plot on. If not provided, 
            a new Axes object will be generated.
        proj (str, optional): The projection to use. Valid values are 'polar'
            and None. Default is None.
        vmin (float, optional): The minimum value for the colorbar. Default is
            None.
        vmax (float, optional): The maximum value for the colorbar. Default is
            None.
    """
    if ax is not None and proj is not None and ax.name != proj:
        msg = f"Ax type {ax.name} must match projection, {proj}."
        raise ValueError(msg)
    if ax is None:
        _, ax = plt.subplots(figsize=(6, 6), subplot_kw={"projection": proj})
    if title is None:
        title = "Facet Slope vs. Azimuth"
    if vmin is None:
        vmin = np.nanmin(table)
    if vmax is None:
        vmax = np.nanmax(table)
    if extent is None:
        extent = (0, 90, 360, 0)
    if isinstance(table, (xr.DataArray, xr.Dataset)):
        table = table.transpose("az", "theta")
        extent = (
            table.theta.min(),
            table.theta.max(),
            table.az.min(),
            table.az.max(),
        )

    if proj == "polar":
        # Define polar coords R ~ slope, Theta ~ azimuth
        r = np.linspace(*extent[:2], table.shape[1])
        theta = np.linspace(*extent[2:], table.shape[0])
        R, Theta = np.meshgrid(r, theta)
        p = ax.pcolormesh(
            np.deg2rad(Theta),
            R,
            table,
            cmap=CMAP_R if cmap_r else CMAP,
            vmin=vmin,
            vmax=vmax,
            shading="auto",
            rasterized=True,
            **kwargs,
        )
        ax.set_theta_zero_location("N")
        ax.set_theta_direction(-1)
        ax.set_rlabel_position(15)
        ax.grid("on", lw=0.1, c="k")
        ax.figure.colorbar(p, ax=ax, shrink=0.8, label=clabel)
    else:
        p = ax.imshow(
            table,
            extent=extent,
            aspect=(extent[1] - extent[0]) / (extent[3] - extent[2]),
            cmap=CMAP_R if cmap_r else CMAP,
            vmin=vmin,
            vmax=vmax,
            interpolation="none",
            **kwargs,
        )
        ax.set_xlabel("Facet slope angle [deg]")
        ax.set_ylabel("Facet azimuth angle [deg]")
        ax.figure.colorbar(p, ax=ax, shrink=0.8, label=clabel)
    ax.set_title(title)
    return p