예제 #1
0
def add_labels(grp, labels, pos, fontsize, fontweight='bold'):
    """Add labels to subplots in a figure
    
    Parameters
    ----------
    grp : atm.FigGroup object
        Instance of atm.FigGroup class for the subplots to annotate
    labels : list
        Labels to annotate, e.g. ['a', 'b', 'c']
    pos : list of tuples
        Positions for each label
    fontsize, fontweight
        Text parameters for labels
    """
    try:
        n = len(pos[0])
    except TypeError:
        pos = [pos] * len(labels)
    row, col = 0, 0
    for i in range(len(labels)):
        grp.subplot(row, col)
        atm.text(labels[i], pos[i], fontsize=fontsize, fontweight=fontweight)
        col += 1
        if col == grp.ncol:
            col = 0
            row += 1
    return None
예제 #2
0
def plot_hist(ind, binwidth=5, incl_daystr=True, ax=None, pos=(0.05, 0.7),
              kw={'alpha' : 0.3, 'color' : 'k'}):
    """Plot histogram of onset days.
    """
    if ax is None:
        ax = plt.gca()

    def daystr(day):
        day = round(day)
        mm, dd = atm.jday_to_mmdd(day)
        mon = atm.month_str(mm)
        return '%.0f (%s-%.0f)' % (day, mon, dd)

    if isinstance(ind, pd.Series) or isinstance(ind, xray.DataArray):
        ind = ind.values

    b1 = np.floor(np.nanmin(ind) / binwidth) * binwidth
    b2 = np.ceil(np.nanmax(ind) / binwidth) * binwidth
    bin_edges = np.arange(b1, b2 + 1, binwidth)
    n, bins, _ = ax.hist(ind, bin_edges, **kw)
    ax.set_xlabel('Day of Year')
    ax.set_ylabel('Num of Occurrences')
    if incl_daystr:
        dmean = daystr(np.nanmean(ind))
        dmin = daystr(np.nanmin(ind))
        dmax = daystr(np.nanmax(ind))
    else:
        dmean = '%.0f' % np.nanmean(ind)
        dmin = '%.0f' % np.nanmin(ind)
        dmax = '%.0f' % np.nanmax(ind)
    s = 'Mean %s\n' % dmean + 'Std %.0f\n' % np.nanstd(ind)
    s = s + 'Min %s\n' % dmin + 'Max %s' % dmax
    x0, y0 = pos
    atm.text(s, (x0, y0), ax=ax, horizontalalignment='left')
예제 #3
0
def add_labels(grp, labels, pos, fontsize, fontweight='bold'):
    # Expand pos to list for each subplot, if needed
    try:
        n = len(pos[0])
    except TypeError:
        pos = [pos] * (grp.nrow * grp.ncol)
    i = 0
    for row in range(grp.nrow):
        for col in range(grp.ncol):
            grp.subplot(row, col)
            atm.text(labels[i], pos[i], fontsize=fontsize,
                     fontweight=fontweight)
            i += 1
def plotyear(chp, y, xlims, ylims):
    days = chp["day"].values
    d_onset = chp["onset"][y]
    d_retreat = chp["retreat"][y]
    plt.plot(days, chp["tseries"][y])
    plt.plot(days, chp["tseries_fit"][y])
    plt.plot([d_onset, d_onset], ylims, "k")
    plt.plot([d_retreat, d_retreat], ylims, "k")
    plt.xlim(xlims[0], xlims[1])
    plt.ylim(ylims[0], ylims[1])
    plt.title(years[y])
    atm.text("Onset: %d\nRetreat: %d" % (d_onset, d_retreat), (0.03, 0.83))
    plt.grid()
def plotyear(chp, y, xlims, ylims):
    days = chp['day'].values
    d_onset = chp['onset'][y]
    d_retreat = chp['retreat'][y]
    plt.plot(days, chp['tseries'][y])
    plt.plot(days, chp['tseries_fit_onset'][y])
    plt.plot(days, chp['tseries_fit_retreat'][y])
    plt.plot([d_onset, d_onset], ylims, 'k')
    plt.plot([d_retreat, d_retreat], ylims, 'k')
    plt.xlim(xlims[0], xlims[1])
    plt.ylim(ylims[0], ylims[1])
    plt.title(years[y])
    atm.text('Onset: %d\nRetreat: %d' % (d_onset, d_retreat), (0.03, 0.83))
    plt.grid()
예제 #6
0
def plot_maps(var, days, grp, cmin=0, cmax=20, cint=1, axlims=(5, 35, 60, 100),
                cmap='PuBuGn', res='c', extend='max', cticks=None,
                daypos=(0.05, 0.85)):
    """Lat-lon maps of precip on selected days."""
    clev = np.arange(cmin, cmax + cint/2.0, cint)
    if cticks is None:
        cticks = np.arange(cmin, clev.max() + 1, 2)
    lat1, lat2, lon1, lon2 = axlims
    for day in days:
        grp.next()
        pcp = var.sel(dayrel=day)
        m = atm.init_latlon(lat1, lat2, lon1, lon2, resolution=res)
        m = atm.contourf_latlon(pcp, m=m, clev=clev, axlims=axlims, cmap=cmap,
                                colorbar=False, extend=extend)
        atm.text(day, daypos, fontsize=12, fontweight='bold')
    # plt.colorbar(ax=grp.axes.ravel().tolist(), orientation='vertical',
    #              shrink=0.8, ticks=cticks)
    atm.colorbar_multiplot(orientation='vertical', shrink=0.8, ticks=cticks)
    fix_axes(axlims)
예제 #7
0
def plot_index_years(index, nrow=3, ncol=4,
                     fig_kw={'figsize' : (11, 7), 'sharex' : True,
                             'sharey' : True},
                     gridspec_kw={'left' : 0.1, 'right' : 0.95, 'wspace' : 0.05,
                                  'hspace' : 0.1},
                     incl_fit=False, suptitle='', xlabel='Day', ylabel='Index',
                     xlims=None, ylims=None, xticks=np.arange(0, 401, 100),
                     grid=True):
    """Plot daily timeseries of monsoon onset/retreat index each year.
    """

    years = atm.get_coord(index, 'year')
    days = atm.get_coord(index, 'day')
    grp = atm.FigGroup(nrow, ncol, fig_kw=fig_kw, gridspec_kw=gridspec_kw,
                       suptitle=suptitle)
    for year in years:
        grp.next()
        ind = atm.subset(index, {'year' : (year, year)}, squeeze=True)
        ts = ind['tseries']
        d0_list = [ind['onset'], ind['retreat']]
        plt.plot(days, ts, 'k')
        for d0 in d0_list:
            plt.axvline(d0, color='k')
        if incl_fit and 'tseries_fit_onset' in ind:
            plt.plot(days, ind['tseries_fit_onset'], 'r')
        if incl_fit and 'tseries_fit_retreat' in ind:
            plt.plot(days, ind['tseries_fit_retreat'], 'b')
        atm.text(year, (0.05, 0.9))
        atm.ax_lims_ticks(xlims=xlims, ylims=ylims, xticks=xticks)
        plt.grid(grid)
        if grp.row == grp.nrow - 1:
            plt.xlabel(xlabel)
        if grp.col == 0:
            plt.ylabel(ylabel)

    return grp
예제 #8
0
ts = index[onset_nm]["tseries"].sel(year=year)
ts_onset = index[onset_nm]["tseries_fit_onset"].sel(year=year)
ts_retreat = index[onset_nm]["tseries_fit_retreat"].sel(year=year)
days = index[onset_nm]["tseries"]["day"]

figsize = (5, 3.5)
gs_kw = {"left": 0.15, "bottom": 0.15}
plt.subplots(1, 1, figsize=figsize, gridspec_kw=gs_kw)
plt.plot(days, ts, "k")
plt.plot(days, ts_onset, "r")
plt.plot(days, ts_retreat, "b")
plt.grid()
plt.xlim(0, 366)
plt.xlabel("Day")
plt.ylabel("MFC_ACC (mm)")
atm.text(year, (0.05, 0.9))


# ----------------------------------------------------------------------
# Summarize onset, retreat, indices in dataframes

onset = pd.DataFrame()
for nm in index:
    onset[nm] = index[nm]["onset"].to_series()
corr = onset.corr()
retreat = index[onset_nm]["retreat"].to_series()
length = retreat - onset[onset_nm]

# Labels for onset indices correlations
labels = {}
for nm in onset.columns:
예제 #9
0
    tseries.plot(ax=ax, grid=True, legend=False)
    ax.set_title(title, loc='left', fontsize=11)

# Plot climatology and a few individual years
plotyears = [None, years[0], years[1], years[2]]
plt.figure(figsize=(12, 9))
suptitle = version.upper() + ' MFC Budget (%s) - Daily Tseries' % latlonstr
plt.suptitle(suptitle)
nrow, ncol = 2, 2
for y, year in enumerate(plotyears):
    ax = plt.subplot(nrow, ncol, y + 1)
    plot_tseries(ts, year, ax=ax)
    if y == 0:
        ax.legend(loc='upper left', fontsize=9)
        s = 'RESID = MFC-P+E-dW/dt-ANA'
        atm.text(s, (0.03, 0.5), fontsize=9)

# ----------------------------------------------------------------------
# Plot daily timeseries of W

W = ts['W']
d1, d2 = days_ssn[0], days_ssn[-1]
W1 = W.sel(day=d1)
W2 = W.sel(day=d2)
plotyears = years[:4]
clrs = ['b', 'r', 'g', 'k']
plt.figure()
for y, year in enumerate(plotyears):
    plt.plot(W['day'], W[y], clrs[y], label=year)
    plt.plot([d1, d2], [W1[y], W2[y]], clrs[y], marker='.')
plt.grid()
예제 #10
0
def plot_tseries_together(data, onset=None, years=None, suptitle='',
                          figsize=(14,10), legendsize=10,
                          legendloc='lower right', nrow=3, ncol=4,
                          yearnm='year', daynm='day', standardize=True,
                          label_attr=None, data_style=None, onset_style=None,
                          show_days=False):
    """Plot multiple daily timeseries together each year.

    Parameters
    ----------
    data : xray.Dataset
        Dataset of timeseries variables to plot together.
    onset : ndarray or dict of ndarrays, optional
        Array of onset day for each year, or dict of onset arrays (e.g.
        to compare onset days from different methods).
    years : ndarray, optional
        Subset of years to include.  If omitted, all years are included.
    suptitle : str, optional
        Supertitle for plot.
    figsize : 2-tuple, optional
        Size of each figure.
    legendsize : int, optional
        Font size for legend
    legendloc : str, optional
        Legend location
    nrow, ncol : int, optional
        Number of rows, columns in each figure.
    yearnm, daynm : str, optional
        Name of year and day dimensions in data.
    standardize : bool, optional
        If True, standardize each timeseries by dividing by its
        standard deviation.
    label_attr : str, optional
        Attribute of each data variable to use for labels.  If omitted,
        then the variable name is used.
    data_style, onset_style : list or dict, optional
        Matlab-style strings for each data variable or onset index.
    show_days : bool, optional
        If True, annotate each subplot with a textbox showing the
        onset days.
    """

    if years is None:
        # All years
        years = data[yearnm].values
    data = atm.subset(data, {yearnm : (years, None)})

    if label_attr is not None:
        labels = {nm : data[nm].attrs[label_attr] for nm in data.data_vars}

    if onset is not None:
        if isinstance(onset, dict):
            if onset_style is None:
                onset_style = {key : 'k' for key in onset.keys()}
        else:
            onset = {'onset' : onset}
            if onset_style is None:
                onset_style = {'onset' : 'k'}
        textpos = {key : (0.05, 0.9 - 0.1*i) for i, key in enumerate(onset)}

    # Plot each year
    for y, year in enumerate(years):
        df = atm.subset(data, {yearnm : (year, None)}).to_dataframe()
        df.drop(yearnm, axis=1, inplace=True)
        if label_attr is not None:
            df.rename(columns=labels, inplace=True)

        if standardize:
            for key in df.columns:
                df[key] = (df[key] - np.nanmean(df[key])) / np.nanstd(df[key])
            ylabel = 'Standardized Timeseries'
        else:
            ylabel = 'Timeseries'

        if y % (nrow * ncol) == 0:
            fig, axes = plt.subplots(nrow, ncol, figsize=figsize, sharex=True)
            plt.subplots_adjust(left=0.08, right=0.95, wspace=0.2, hspace=0.2)
            plt.suptitle(suptitle)
            yplot = 1
        else:
            yplot += 1

        i, j = atm.subplot_index(nrow, ncol, yplot)
        ax = axes[i-1, j-1]
        df.plot(ax=ax, style=data_style)
        ax.grid()
        if yplot == 1:
            ax.legend(fontsize=legendsize, loc=legendloc)
        else:
            ax.legend_.remove()
        if onset is not None:
            for key in onset:
                d0 = onset[key][y]
                ax.plot([d0, d0], ax.get_ylim(), onset_style[key])
                if show_days:
                    atm.text(d0, textpos[key], ax=ax, color=onset_style[key])
        if j == 1:
            ax.set_ylabel(ylabel)
        if i == nrow:
            ax.set_xlabel('Day')
        else:
            ax.set_xlabel('')
        ax.set_title(year)
예제 #11
0
        if key.startswith('CHP'):
            for nm, clr in zip(['onset', 'retreat'], ['r', 'g']):
                pred = index[keylong]['tseries_fit_' + nm][y]
                pred = atm.subset(pred, {'day' : (df.index, None)})
                ax.plot(df.index, pred, clr)
        if std_ts:
            ax.set_ylim(ylim1, ylim2)
        else:
            plt.autoscale(tight=True)
        ax.plot([d0, d0], ax.get_ylim(), style)
        txt = '%d' % d0
        if d1 is not None:
            ax.plot([d1, d1], ax.get_ylim(), style)
            txt = txt + ', %d' % d1
        ax.grid()
        atm.text(txt, (0.05, 0.9), ax=ax, color=style)

        if i == 0:
            ax.set_title(year)
        if i == nrow - 1:
            ax.set_xlabel('Day')
        else:
            ax.set_xlabel('')
        if y % ncol == 0:
            ax.set_ylabel(key)
        iplot += ncol

saveclose('tseries_stacked_', isave, exts)


# Correlations between daily timeseries
예제 #12
0
    style = {'MFC' : 'k', pcp_nm : 'k--'}
    fig_kw = {'figsize' : (14, 10)}
    gridspec_kw = {'left' : 0.04, 'right' : 0.94, 'bottom' : 0.06, 'top' : 0.95,
                   'hspace' : 0.07, 'wspace' : 0.07}
    suptitle = 'Daily and Cumulative Precip/MFC for %s Onset' % onset_nm
    nrow, ncol = 3, 4
    grp = atm.FigGroup(nrow, ncol, fig_kw=fig_kw, gridspec_kw=gridspec_kw,
                       suptitle=suptitle)
    for y, year in enumerate(years):
        grp.next()
        if grp.row == 0 and grp.col == ncol - 1:
            legend = True
        else:
            legend = False
        data1 = xray.Dataset({'MFC' : data['MFC'][y], pcp_nm : data[pcp_nm][y]})
        data2 = data['MFC_ACC'][y]
        axes = lineplots(data1, data2, style, xlims, xticks, ylims, yticks,
                         y2_lims=y2_lims, legend=legend,
                         length=index['length'][y])
        title = '%d\n%d, %d' % (year, onset[y], index['retreat'][y])
        atm.text(title, (0.03, 0.85), fontsize=10)
        if grp.row < nrow - 1:
            for ax in axes:
                clear_labels('x', ax)

        for i, ax in enumerate(axes):
            if i == 0 and grp.col > 0:
                clear_labels('y', ax)
            if i > 0 and grp.col < ncol - 1:
                clear_labels('y', ax)
예제 #13
0
    yrly_index(onset_all, legend=True)
else:
    for i in [0, 1]:
        grp.next()
        plt.axis('off')
    ax = plt.subplot(2, 1, 1)
    df = index[['length', 'retreat', 'onset']].to_dataframe()
    plt.boxplot(df.values, vert=False, labels=['Length', 'Retreat', 'Onset'],
                whis='range')
    plt.xlabel('Day of Year | Number of Days')
    plt.xlim(120, 320)
    plt.xticks(np.arange(120, 321, 20))
    pos = ax.get_position()
    pos2 = [pos.x0, pos.y0 + 0.05, pos.width, pos.height]
    ax.set_position(pos2)
    atm.text('a', (-0.16, 1.01), fontsize=labelsize, fontweight='bold')

# Plot daily tseries
legend = True
if ind_nm == 'onset':
    dlist = [15]
else:
    dlist = None
daily_tseries(tseries, index, pcp_nm, npre, npost, legend, grp, ind_nm=ind_nm,
              dlist=dlist)

# Add a-d labels
if ind_nm == 'onset':
    labels = ['a', 'b', 'c', 'd']
    add_labels(grp, labels, labelpos, labelsize)
else: