# This software is open source software available under the BSD-3 license.
#
# Copyright (c) 2022 Triad National Security, LLC. All rights reserved.
# Copyright (c) 2022 Lawrence Livermore National Security, LLC. All rights
# reserved.
# Copyright (c) 2022 UT-Battelle, LLC. All rights reserved.
#
# Additional copyright and license information can be found in the LICENSE file
# distributed with this code, or at
# https://raw.githubusercontent.com/MPAS-Dev/MPAS-Analysis/main/LICENSE
"""
Plotting utilities, including routines for plotting:
    * time series (and comparing with reference data sets)
    * remapped horizontal fields (and comparing with reference data sets)
    * vertical sections on native grid
    * NINO34 time series and spectra
"""
# Authors
# -------
# Xylar Asay-Davis, Milena Veneziani, Luke Van Roekel, Greg Streletz
import matplotlib
import matplotlib.pyplot as plt
from mpas_analysis.shared.plot.title import limit_title
from mpas_analysis.shared.plot.save import savefig
[docs]
def plot_1D(config, xArrays, fieldArrays, errArrays,
            lineColors=None, lineStyles=None, markers=None, lineWidths=None,
            legendText=None, title=None, xlabel=None, ylabel=None,
            fileout='plot_1D.png',
            figsize=(10, 4), dpi=None,
            xLim=None,
            yLim=None,
            invertYAxis=False,
            maxTitleLength=None,
            titleFontSize=None,
            axisFontSize=None,
            defaultFontSize=None):
    """
    Plots a 1D line plot with error bars if available.
    Parameters
    ----------
    config : instance of ConfigParser
        the configuration, containing a [plot] section with options that
        control plotting
    xArrays : list of float arrays
        x array (latitude, or any other x axis except time)
    fieldArrays : list of float arrays
        y array (any field as function of x)
    errArrays : list of float arrays
        error array (y errors)
    lineColors, lineStyles, markers, legendText : list of str, optional
        control line color, style, marker, and corresponding legend
        text.  Default is black, solid line with no marker, and no legend.
    lineWidths : list of float, optional
        control line width.  Default is 1.0.
    title : str, optional
        title of plot
    xlabel, ylabel : str, optional
        label of x- and y-axis
    fileout : str, optional
        the file name to be written
    figsize : tuple of float, optional
        size of the figure in inches
    dpi : int, optional
        the number of dots per inch of the figure, taken from section ``plot``
        option ``dpi`` in the config file by default
    xLim : float array, optional
        x range of plot
    yLim : float array, optional
        y range of plot
    invertYAxis : logical, optional
        if True, invert Y axis
    maxTitleLength : int or None, optional
        the maximum number of characters in the title, beyond which it is
        truncated with a trailing ellipsis.  The default is from the
        ``maxTitleLength`` config option.
    titleFontSize : int, optional
        size of the title font
    axisFontSize : int, optional
        size of the title font
    defaultFontSize : int, optional
        the size of text other than the title
    """
    # Authors
    # -------
    # Mark Petersen, Milena Veneziani, Xylar Asay-Davis
    if maxTitleLength is None:
        maxTitleLength = config.getint('plot', 'maxTitleLength')
    if defaultFontSize is None:
        defaultFontSize = config.getint('plot', 'defaultFontSize')
    matplotlib.rc('font', size=defaultFontSize)
    # set up figure
    if dpi is None:
        dpi = config.getint('plot', 'dpi')
    plt.figure(figsize=figsize, dpi=dpi)
    plotLegend = False
    for dsIndex in range(len(xArrays)):
        xArray = xArrays[dsIndex]
        fieldArray = fieldArrays[dsIndex]
        errArray = errArrays[dsIndex]
        if xArray is None:
            continue
        if legendText is None:
            label = None
        else:
            label = legendText[dsIndex]
            if label is not None:
                label = limit_title(label, maxTitleLength)
            plotLegend = True
        if lineColors is None:
            color = 'k'
        else:
            color = lineColors[dsIndex]
        if markers is None:
            marker = None
        else:
            marker = markers[dsIndex]
        if lineStyles is None:
            linestyle = '-'
        else:
            linestyle = lineStyles[dsIndex]
        if lineWidths is None:
            linewidth = 1.
        else:
            linewidth = lineWidths[dsIndex]
        plt.plot(xArray, fieldArray, color=color, linestyle=linestyle,
                 marker=marker, linewidth=linewidth, label=label)
        if errArray is not None:
            plt.fill_between(xArray, fieldArray, fieldArray + errArray,
                             facecolor=color, alpha=0.2)
            plt.fill_between(xArray, fieldArray, fieldArray - errArray,
                             facecolor=color, alpha=0.2)
    plt.grid()
    plt.axhline(0.0, linestyle='-', color='k')  # horizontal lines
    if plotLegend and len(xArrays) > 1:
        plt.legend()
    if titleFontSize is None:
        titleFontSize = config.get('plot', 'titleFontSize')
    if axisFontSize is None:
        axisFontSize = config.get('plot', 'axisFontSize')
    axis_font = {'size': axisFontSize}
    title_font = {'size': titleFontSize,
                  'color': config.get('plot', 'titleFontColor'),
                  'weight': config.get('plot', 'titleFontWeight')}
    if title is not None:
        title = limit_title(title, max_title_length=maxTitleLength)
        plt.title(title, **title_font)
    if xlabel is not None:
        plt.xlabel(xlabel, **axis_font)
    if ylabel is not None:
        plt.ylabel(ylabel, **axis_font)
    if invertYAxis:
        plt.gca().invert_yaxis()
    if xLim:
        plt.xlim(xLim)
    if yLim:
        plt.ylim(yLim)
    if fileout is not None:
        savefig(fileout, config)
    plt.close()