Skip to content

Plot Summary

pbp.plotting.plot_dataset_summary(ds, lat_lon_for_solpos=DEFAULT_LAT_LON_FOR_SOLPOS, title=DEFAULT_TITLE, ylim=DEFAULT_YLIM, cmlim=DEFAULT_CMLIM, dpi=DEFAULT_DPI, jpeg_filename=None, show=False)

Generate a summary plot from the given dataset.

Parameters:

Name Type Description Default
ds Dataset

Dataset to plot.

required
lat_lon_for_solpos tuple[float, float]

Lat/Lon for solar position calculation.

DEFAULT_LAT_LON_FOR_SOLPOS
title str

Title for the plot.

DEFAULT_TITLE
ylim tuple[int, int]

Limits for the y-axis.

DEFAULT_YLIM
cmlim tuple[int, int]

Limits passed to pcolormesh.

DEFAULT_CMLIM
dpi int

DPI to use for the plot.

DEFAULT_DPI
jpeg_filename Optional[str]

If given, filename to save the plot to.

None
show bool

Whether to show the plot.

False
Source code in pbp/plotting.py
 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
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
def plot_dataset_summary(
    ds: xr.Dataset,
    lat_lon_for_solpos: tuple[float, float] = DEFAULT_LAT_LON_FOR_SOLPOS,
    title: str = DEFAULT_TITLE,
    ylim: tuple[int, int] = DEFAULT_YLIM,
    cmlim: tuple[int, int] = DEFAULT_CMLIM,
    dpi: int = DEFAULT_DPI,
    jpeg_filename: Optional[str] = None,
    show: bool = False,
):  # pylint: disable=R0915  too-many-statements
    # Code by RYJO, with some typing/formatting/variable naming adjustments.
    """
    Generate a summary plot from the given dataset.
    :param ds: Dataset to plot.
    :param lat_lon_for_solpos: Lat/Lon for solar position calculation.
    :param title: Title for the plot.
    :param ylim: Limits for the y-axis.
    :param cmlim: Limits passed to pcolormesh.
    :param dpi: DPI to use for the plot.
    :param jpeg_filename: If given, filename to save the plot to.
    :param show: Whether to show the plot.
    """
    plt.rcParams["text.usetex"] = False
    plt.rcParams["axes.edgecolor"] = "black"

    # Transpose psd array for plotting
    da = xr.DataArray.transpose(ds.psd)

    # get solar elevation
    # Estimate the solar position with a specific SPA defined with the argument 'method'
    latitude, longitude = lat_lon_for_solpos
    solpos = pvlib.solarposition.get_solarposition(
        ds.time, latitude=latitude, longitude=longitude
    )
    se = solpos.elevation  # isolate solar elevation
    # map elevation to gray scale
    seg = 0 * se  # 0 covers nighttime (black)
    # day (white)
    d = np.squeeze(np.where(se > 0))
    seg.iloc[d] = 1
    # dusk / dawn (gray range)
    d = np.squeeze(np.where(np.logical_and(se <= 0, se >= -12)))
    seg.iloc[d] = 1 - abs(se.iloc[d] / max(abs(se.iloc[d])))
    # Get the indices of the min and max
    seg1 = pd.Series.to_numpy(solpos.elevation)
    minidx = np.squeeze(np.where(seg1 == min(seg1)))
    maxidx = np.squeeze(np.where(seg1 == max(seg1)))

    seg3 = np.tile(seg, (50, 1))

    # plotting variables

    psdlabl = (
        r"Spectrum level (dB re 1 $\mu$Pa$\mathregular{^{2}}$ Hz$\mathregular{^{-1}}$)"
    )
    freqlabl = "Frequency (Hz)"

    # define percentiles
    pctlev = np.array([1, 10, 25, 50, 75, 90, 99])
    # initialize output array
    pctls = np.empty((pctlev.size, ds.frequency.size))
    # get percentiles
    np.nanpercentile(ds.psd, pctlev, axis=0, out=pctls)

    # create a figure
    fig = plt.figure()
    fig.set_figheight(6)
    fig.set_figwidth(12)
    spec = gridspec.GridSpec(
        ncols=2,
        nrows=2,
        width_ratios=[2.5, 1],
        wspace=0.02,
        height_ratios=[0.045, 0.95],
        hspace=0.09,
    )

    # Use more of the available plotting space
    plt.subplots_adjust(left=0.06, right=0.94, bottom=0.12, top=0.89)

    # Spectrogram
    ax0 = fig.add_subplot(spec[2])
    vmin, vmax = cmlim
    sg = plt.pcolormesh(
        ds.time, ds.frequency, da, shading="nearest", cmap="rainbow", vmin=vmin, vmax=vmax
    )
    plt.yscale("log")
    plt.ylim(list(ylim))
    plt.ylabel(freqlabl)
    xl = ax0.get_xlim()
    ax0.set_xticks([])
    # plt.colorbar(location='left', shrink = 0.25, fraction = 0.05)

    # Percentile
    pplabels = ["L99", "L90", "L75", "L50", "L25", "L10", "L1"]
    ax1 = fig.add_subplot(spec[3])
    ax1.yaxis.tick_right()
    ax1.yaxis.set_label_position("right")
    plt.plot(pctls.T, ds.frequency, linewidth=1)
    plt.yscale("log")
    plt.ylim(list(ylim))
    plt.xlabel(psdlabl)
    plt.ylabel(freqlabl)
    plt.legend(loc="lower left", labels=pplabels)

    # day night
    ax3 = fig.add_subplot(spec[0])
    ax3.pcolormesh(seg3, shading="flat", cmap="gray")
    ax3.annotate("Day", (maxidx, 25), weight="bold", ha="center", va="center")
    ax3.annotate(
        "Night", (minidx, 25), weight="bold", color="white", ha="center", va="center"
    )
    ax3.set_xticks([])
    ax3.set_yticks([])

    # colorbar for spectrogram
    r = np.concatenate(np.squeeze(ax0.get_position()))
    cb_ax = fig.add_axes([r[0] + 0.09, r[1] - 0.025, r[2] - 0.25, 0.015])
    q = fig.colorbar(sg, orientation="horizontal", cax=cb_ax)
    q.set_label(psdlabl)

    # time axes for the day/night panel
    # create a dummy time / zero range variable
    timax = fig.add_axes(ax3.get_position(), frameon=False)
    timax.plot(solpos.elevation * 0, "k")
    timax.tick_params(top=True, labeltop=True, bottom=False, labelbottom=False)
    timax.set_ylim(0, 100)
    timax.set_yticks([])
    timax.set_xlim(xl)
    timax.xaxis.set_major_formatter(
        md.ConciseDateFormatter(timax.xaxis.get_major_locator())
    )

    plt.gcf().text(0.5, 0.955, title, fontsize=14, horizontalalignment="center")
    plt.gcf().text(0.65, 0.91, "UTC")

    if jpeg_filename is not None:
        plt.savefig(jpeg_filename, dpi=dpi)
    if show:
        plt.show()
    plt.close(fig)