"""
pyrad.graph.plot_timeseries
===========================

Functions to plot Pyrad datasets

.. autosummary::
    :toctree: generated/

    plot_timeseries
    plot_timeseries_comp
    plot_monitoring_ts
    plot_intercomp_scores_ts
    plot_ml_ts
    plot_sun_retrieval_ts

"""

import pyart
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from warnings import warn

import numpy as np
import datetime

import matplotlib as mpl

mpl.use("Agg")

# Increase a bit font size
mpl.rcParams.update({"font.size": 16})
mpl.rcParams.update({"font.family": "sans-serif"})


def plot_timeseries(
    tvec,
    data_list,
    fname_list,
    labelx="Time [UTC]",
    labely="Value",
    labels=["Sensor"],
    title="Time Series",
    period=0,
    timeformat=None,
    colors=None,
    linestyles=None,
    markers=None,
    ymin=None,
    ymax=None,
    dpi=72,
):
    """
    plots a time series

    Parameters
    ----------
    tvec : datetime object
        time of the time series
    data_list : list of float array
        values of the time series
    fname_list : list of str
        list of names of the files where to store the plot
    labelx : str
        The label of the X axis
    labely : str
        The label of the Y axis
    labels : array of str
        The label of the legend
    title : str
        The figure title
    period : float
        measurement period in seconds used to compute accumulation. If 0 no
        accumulation is computed
    timeformat : str
        Specifies the tvec and time format on the x axis
    colors : array of str
        Specifies the colors of each line
    linestyles : array of str
        Specifies the line style of each line
    markers: array of str
        Specify the markers to be used for each line
    ymin, ymax: float
        Lower/Upper limit of y axis
    dpi : int
        dots per inch

    Returns
    -------
    fname_list : list of str
        list of names of the created plots

    History
    --------
    201?.??.?? -fvj- creation
    2017.08.21 -jgr- modified margins and grid + minor graphical updates
    2018.03.05 -jgr- added x-limit of x axis to avoid unwanted error messages

    """
    tvec = np.array(tvec)  # convert  from pandas if needed
    if period > 0:
        for i, data in enumerate(data_list):
            data *= period / 3600.0
            data_list[i] = np.ma.cumsum(data)

    fig, ax = plt.subplots(figsize=[10, 6], dpi=dpi)

    lab = None
    col = None
    lstyle = "--"
    marker = "o"

    for i, data in enumerate(data_list):
        if labels is not None:
            lab = labels[i]
        if colors is not None:
            col = colors[i]
        if linestyles is not None:
            lstyle = linestyles[i]
        if markers is not None:
            marker = markers[i]
        ax.plot(tvec, data, label=lab, color=col, linestyle=lstyle, marker=marker)

    ax.set_title(title)
    ax.set_xlabel(labelx)
    ax.set_ylabel(labely)
    ax.set_ylim(bottom=ymin, top=ymax)
    ax.set_xlim([tvec[0], tvec[-1]])

    # Turn on the grid
    ax.grid()

    if timeformat is not None:
        ax.xaxis.set_major_formatter(mdates.DateFormatter(timeformat))

    # rotates and right aligns the x labels, and moves the bottom of the
    # axes up to make room for them
    fig.autofmt_xdate()

    # Make a tight layout
    fig.tight_layout()

    for fname in fname_list:
        fig.savefig(fname, dpi=dpi)
    plt.close(fig)

    return fname_list


def plot_timeseries_comp(
    date1,
    value1,
    date2,
    value2,
    fname_list,
    labelx="Time [UTC]",
    labely="Value",
    label1="Sensor 1",
    label2="Sensor 2",
    titl="Time Series Comparison",
    period1=0,
    period2=0,
    ymin=None,
    ymax=None,
    dpi=72,
):
    """
    plots 2 time series in the same graph

    Parameters
    ----------
    date1 : datetime object
        time of the first time series
    value1 : float array
        values of the first time series
    date2 : datetime object
        time of the second time series
    value2 : float array
        values of the second time series
    fname_list : list of str
        list of names of the files where to store the plot
    labelx : str
        The label of the X axis
    labely : str
        The label of the Y axis
    label1, label2 : str
        legend label for each time series
    titl : str
        The figure title
     period1, period2 : float
        measurement period in seconds used to compute accumulation. If 0 no
        accumulation is computed
    dpi : int
        dots per inch
    ymin, ymax : float
        The limits of the Y-axis. None will keep the default limit.

    Returns
    -------
    fname_list : list of str
        list of names of the created plots

    History
    --------
    201?.??.?? -fvj- created
    2017.08.21 -jgr- changed some graphical aspects

    """
    if (period1 > 0) and (period2 > 0):
        # TODO: document this and check (sometimes artefacts)
        value1 *= period1 / 3600.0
        value1 = np.ma.cumsum(value1)

        value2 *= period2 / 3600.0
        value2 = np.ma.cumsum(value2)

    fig, ax = plt.subplots(figsize=[10, 6.5], dpi=dpi)
    ax.plot(date1, value1, "b", label=label1, linestyle="--", marker="o")
    ax.plot(date2, value2, "r", label=label2, linestyle="--", marker="s")
    ax.legend(loc="best")
    ax.set_xlabel(labelx)
    ax.set_ylabel(labely)
    ax.set_title(titl)

    ax.grid()

    ax.set_ylim(bottom=ymin, top=ymax)
    ax.set_xlim([date2[0], date2[-1]])

    # rotates and right aligns the x labels, and moves the bottom of the
    # axes up to make room for them
    fig.autofmt_xdate()

    # Make a tight layout
    fig.tight_layout()

    for fname in fname_list:
        fig.savefig(fname, dpi=dpi)
    plt.close(fig)

    return fname_list


def plot_monitoring_ts(
    date,
    np_t,
    val_mean_and_quant,
    quantiles,
    field_name,
    fname_list,
    ref_value=None,
    vmin=None,
    vmax=None,
    np_min=0,
    labelx="Time [UTC]",
    labely="Value",
    titl="Time Series",
    dpi=72,
    plot_until_year_end=False,
):
    """
    Plots a time series of monitoring data.

    Parameters
    ----------
    date : datetime object
        Time of the time series.
    np_t : int array
        Number of points.
    val_mean_and_quant : float array
        Values of the mean in dB, mean in dB computed from linear units,
        followed by all quantiles.
    quantiles : 1D ndarray
        The computed quantiles.
    field_name : str
        Name of the field.
    fname_list : list of str
        List of filenames where to store the plot.
    ref_value : float, optional
        The reference value.
    vmin, vmax : float, optional
        Limits of the y-axis.
    np_min : int, optional
        Minimum number of points to consider the sample plottable.
    labelx : str, optional
        Label for the X-axis.
    labely : str, optional
        Label for the Y-axis.
    titl : str, optional
        The figure title.
    dpi : int, optional
        Dots per inch.
    plot_until_year_end : bool, optional
        If True, sets the maximum x-tick to the end of the year.

    Returns
    -------
    fname_list : list of str
        List of filenames of the created plots.
    """

    # Get default Py-ART field limits
    vmin_pyart, vmax_pyart = pyart.config.get_field_limits(field_name)
    if vmin is None:
        vmin = vmin_pyart
    if vmax is None:
        vmax = vmax_pyart

    date = np.array(date)

    # Separate mean values and quantiles from val_mean_and_quant
    geometric_mean_dB = val_mean_and_quant[:, 0]
    linear_mean_dB = val_mean_and_quant[:, 1]
    quantile_values = val_mean_and_quant[:, 2:]

    # Define colors for plotting
    quantile_colors = plt.cm.viridis_r(np.linspace(0, 1, len(quantiles)))

    # Determine valid data points
    isvalid = np.logical_not(np.ma.getmaskarray(geometric_mean_dB))
    if np_min > 0:
        has_np = np_t > np_min
        isvalid = np.logical_and(isvalid, has_np)

    date_plt = date[isvalid]
    mean_dB_plt = geometric_mean_dB[isvalid]
    mean_dB_from_lin_plt = linear_mean_dB[isvalid]
    quantile_values_plt = quantile_values[isvalid]

    fig = plt.figure(figsize=[15, 13], dpi=dpi)

    ax = fig.add_subplot(2, 1, 1)

    # Plot means
    ax.plot(date_plt, mean_dB_plt, "rx--", label="Geometric mean")
    ax.plot(date_plt, mean_dB_from_lin_plt, "bx--", label="Linear mean")

    # Plot all quantiles dynamically
    for i, q in enumerate(quantiles):
        ax.plot(
            date_plt,
            quantile_values_plt[:, i],
            "x-",
            color=quantile_colors[i],
            label=f"Q{q}",
        )

    # Plot reference value if provided
    if ref_value is not None:
        ax.axhline(ref_value, color="k", linestyle="--", label="Reference")

    ax.set_ylabel(labely)
    ax.set_title(titl)
    ax.set_ylim([vmin, vmax])
    ax.grid(True)
    ax.legend(loc="best")

    # Adjust x-axis limits
    if plot_until_year_end:
        t0 = date_plt[0]
        tend = datetime.datetime(year=t0.year, month=12, day=31, hour=23, minute=59)
        ax.set_xlim([t0, tend])
    else:
        ax.autoscale(enable=True, axis="x", tight=True)
        ax.set_xlim([date_plt[0], date_plt[-1]])

    # Second subplot for NP values
    ax = fig.add_subplot(2, 1, 2)
    ax.plot(date, np_t, "x-", label="Number of Samples")

    if np_min is not None:
        ax.axhline(np_min, color="k", linestyle="--", label=f"Min NP ({np_min})")

    if plot_until_year_end:
        ax.set_xlim([t0, tend])
    else:
        ax.autoscale(enable=True, axis="x", tight=True)
        ax.set_xlim([date_plt[0], date_plt[-1]])

    ax.set_ylabel("Number of Samples")
    ax.set_xlabel(labelx)
    ax.legend(loc="best")
    fig.autofmt_xdate()

    plt.tight_layout()

    # Save figure
    for fname in fname_list:
        fig.savefig(fname, dpi=dpi)
    plt.close(fig)

    return fname_list


def plot_intercomp_scores_ts(
    date_vec,
    np_vec,
    meanbias_vec,
    medianbias_vec,
    quant25bias_vec,
    quant75bias_vec,
    modebias_vec,
    corr_vec,
    slope_vec,
    intercep_vec,
    intercep_slope1_vec,
    fname_list,
    ref_value=0.0,
    np_min=0,
    corr_min=0.0,
    labelx="Time UTC",
    titl="RADAR001-RADAR002 intercomparison",
    dpi=72,
):
    """
    plots a time series of radar intercomparison scores

    Parameters
    ----------
    date_vec : datetime object
        time of the time series
    np_vec : int array
        number of points
    meanbias_vec, medianbias_vec, modebias_vec : float array
        mean, median and mode bias
    quant25bias_vec, quant75bias_vec: 25th and 75th percentile of the bias
    corr_vec : float array
        correlation
    slope_vec, intercep_vec : float array
        slope and intercep of a linear regression
    intercep_slope1_vec : float
        the intercep point of a inear regression of slope 1
    ref_value : float
        the reference value
    np_min : int
        The minimum number of points to consider the result valid
    corr_min : float
        The minimum correlation to consider the results valid
    labelx : str
        The label of the X axis
    titl : str
        The figure title

    Returns
    -------
    fname_list : list of str
        list of names of the created plots

    """
    # plot only valid data (but keep first and last date)
    date2 = np.array(date_vec)
    isvalid = np.logical_not(np.ma.getmaskarray(meanbias_vec))
    isvalid_corr = np.logical_not(np.ma.getmaskarray(corr_vec))
    if np_min > 0:
        has_np = np_vec > np_min
        isvalid = np.logical_and(isvalid, has_np)
    if corr_min > 0:
        has_corr_min = corr_vec > corr_min
        isvalid = np.logical_and(isvalid, has_corr_min)

    meanbias_plt = meanbias_vec[isvalid]
    medianbias_plt = medianbias_vec[isvalid]
    quant25bias_plt = quant25bias_vec[isvalid]
    quant75bias_plt = quant75bias_vec[isvalid]
    modebias_plt = modebias_vec[isvalid]
    intercep_plt = intercep_slope1_vec[isvalid]
    corr_plt = corr_vec[isvalid_corr]
    date_corr = date2[isvalid_corr]
    date_plt = date2[isvalid]
    if not isvalid[0]:
        meanbias_plt = np.ma.append(np.ma.masked, meanbias_plt)
        medianbias_plt = np.ma.append(np.ma.masked, medianbias_plt)
        quant25bias_plt = np.ma.append(np.ma.masked, quant25bias_plt)
        quant75bias_plt = np.ma.append(np.ma.masked, quant75bias_plt)
        modebias_plt = np.ma.append(np.ma.masked, modebias_plt)
        intercep_plt = np.ma.append(np.ma.masked, intercep_plt)
        date_plt = np.ma.append(date2[0], date_plt)
    if not isvalid[-1]:
        meanbias_plt = np.ma.append(meanbias_plt, np.ma.masked)
        medianbias_plt = np.ma.append(medianbias_plt, np.ma.masked)
        quant25bias_plt = np.ma.append(quant25bias_plt, np.ma.masked)
        quant75bias_plt = np.ma.append(quant75bias_plt, np.ma.masked)
        modebias_plt = np.ma.append(modebias_plt, np.ma.masked)
        intercep_plt = np.ma.append(intercep_plt, np.ma.masked)
        date_plt = np.ma.append(date_plt, date2[-1])

    if not isvalid_corr[0]:
        corr_plt = np.ma.append(np.ma.masked, corr_plt)
        date_corr = np.ma.append(date2[0], date_corr)
    if not isvalid_corr[-1]:
        corr_plt = np.ma.append(corr_plt, np.ma.masked)
        date_corr = np.ma.append(date_corr, date2[-1])

    fig = plt.figure(figsize=[10, 20], dpi=dpi)

    ax = fig.add_subplot(4, 1, 1)
    ax.plot(date_plt, medianbias_plt, "bx-", label="median")
    ax.plot(date_plt, meanbias_plt, "rx-", label="mean")
    ax.plot(date_plt, modebias_plt, "gx-", label="mode")
    ax.plot(date_plt, intercep_plt, "yx-", label="intercep of slope 1 LR")
    if ref_value is not None:
        ax.plot(date_plt, np.zeros(len(date_plt)) + ref_value, "k--")
    # plt.legend(loc='best')
    ax.set_ylabel("bias [dB]")
    ax.set_title(titl)
    ax.set_ylim([-5.0, 5.0])

    # tight x axis
    ax.autoscale(enable=True, axis="x", tight=True)
    ax.grid(True)

    ax = fig.add_subplot(4, 1, 2)
    ax.plot(date_plt, medianbias_plt, "bx-", label="median")
    ax.plot(date_plt, quant25bias_plt, "rx-", label="25-percentile")
    ax.plot(date_plt, quant75bias_plt, "rx-", label="75-percentile")
    if ref_value is not None:
        ax.plot(date_plt, np.zeros(len(date_plt)) + ref_value, "k--")
    # plt.legend(loc='best')
    ax.set_ylabel("bias [dB]")
    ax.set_ylim([-5.0, 5.0])

    # tight x axis
    ax.autoscale(enable=True, axis="x", tight=True)
    ax.grid(True)

    ax = fig.add_subplot(4, 1, 3)
    ax.plot(date_corr, corr_plt, "bx-")

    if corr_min > 0:
        ax.plot(date_corr, np.zeros(len(date_corr)) + corr_min, "k--")

    ax.set_ylabel("correlation")
    ax.set_ylim([0.0, 1.0])

    # tight x axis
    ax.autoscale(enable=True, axis="x", tight=True)
    ax.grid(True)

    ax = fig.add_subplot(4, 1, 4)
    ax.plot(date2, np_vec, "bx-")

    if np_min > 0:
        ax.plot(date2, np.zeros(len(date2)) + np_min, "k--")

    ax.set_ylabel("Number of Samples")
    ax.set_xlabel(labelx)

    # tight x axis
    ax.autoscale(enable=True, axis="x", tight=True)

    # rotates and right aligns the x labels, and moves the bottom of the
    # axes up to make room for them
    fig.autofmt_xdate()

    for fname in fname_list:
        fig.savefig(fname, dpi=dpi)
    plt.close(fig)
    return fname_list


def plot_ml_ts(
    dt_ml_arr,
    ml_top_avg_arr,
    ml_top_std_arr,
    thick_avg_arr,
    thick_std_arr,
    nrays_valid_arr,
    nrays_total_arr,
    fname_list,
    labelx="Time UTC",
    titl="Melting layer time series",
    dpi=72,
):
    """
    plots a time series of melting layer data

    Parameters
    ----------
    dt_ml_arr : datetime object
        time of the time series
    np_vec : int array
        number of points
    meanbias_vec, medianbias_vec, modebias_vec : float array
        mean, median and mode bias
    quant25bias_vec, quant75bias_vec: 25th and 75th percentile of the bias
    corr_vec : float array
        correlation
    slope_vec, intercep_vec : float array
        slope and intercep of a linear regression
    intercep_slope1_vec : float
        the intercep point of a inear regression of slope 1
    ref_value : float
        the reference value
    np_min : int
        The minimum number of points to consider the result valid
    corr_min : float
        The minimum correlation to consider the results valid
    labelx : str
        The label of the X axis
    titl : str
        The figure title

    Returns
    -------
    fname_list : list of str
        list of names of the created plots

    """
    fig = plt.figure(figsize=[10, 15], dpi=dpi)

    ax = fig.add_subplot(3, 1, 1)
    ax.plot(dt_ml_arr, ml_top_avg_arr, "bx-", label="avg")
    ax.plot(dt_ml_arr, ml_top_avg_arr + ml_top_std_arr, "rx-", label="avg+std")
    ax.plot(dt_ml_arr, ml_top_avg_arr - ml_top_std_arr, "rx-", label="avg-std")
    # plt.legend(loc='best')
    ax.set_ylabel("Top height [m MSL]")
    ax.set_title(titl)
    ax.set_ylim([0.0, 6000.0])
    ax.set_xlim([dt_ml_arr[0], dt_ml_arr[-1]])

    # tight x axis
    ax.autoscale(enable=True, axis="x", tight=True)
    ax.grid(True)

    ax = fig.add_subplot(3, 1, 2)
    ax.plot(dt_ml_arr, thick_avg_arr, "bx-", label="avg")
    ax.plot(dt_ml_arr, thick_avg_arr + thick_std_arr, "rx-", label="avg+std")
    ax.plot(dt_ml_arr, thick_avg_arr - thick_std_arr, "rx-", label="avg-std")
    # plt.legend(loc='best')
    ax.set_ylabel("Thickness [m]")
    ax.set_ylim([0.0, 3000.0])
    ax.set_xlim([dt_ml_arr[0], dt_ml_arr[-1]])

    # tight x axis
    ax.autoscale(enable=True, axis="x", tight=True)
    ax.grid(True)

    ax = fig.add_subplot(3, 1, 3)
    ax.plot(dt_ml_arr, nrays_valid_arr, "bx-", label="N valid rays")
    ax.plot(dt_ml_arr, nrays_total_arr, "rx-", label="rays total")
    # plt.legend(loc='best')
    ax.set_ylabel("Rays")
    ax.set_xlabel(labelx)
    ax.set_ylim([0, np.max(nrays_total_arr) + 5])
    ax.set_xlim([dt_ml_arr[0], dt_ml_arr[-1]])

    # tight x axis
    ax.autoscale(enable=True, axis="x", tight=True)
    ax.grid(True)

    # rotates and right aligns the x labels, and moves the bottom of the
    # axes up to make room for them
    fig.autofmt_xdate()

    for fname in fname_list:
        fig.savefig(fname, dpi=dpi)
    plt.close(fig)

    return fname_list


def plot_sun_retrieval_ts(
    sun_retrieval,
    data_type,
    fname_list,
    labelx="Date",
    titl="Sun retrieval Time Series",
    dpi=72,
):
    """
    plots sun retrieval time series series

    Parameters
    ----------
    sun_retrieval : tuple
        tuple containing the retrieved parameters
    data_type : str
        parameter to be plotted
    fname_list : list of str
        list of names of the files where to store the plot
    labelx : str
        the x label
    titl : str
        the title of the plot
    dpi : int
        dots per inch

    Returns
    -------
    fname_list : list of str
        list of names of the created plots

    """
    value_std = None
    ref = None
    date = sun_retrieval[1]
    if data_type == "nhits_h":
        value = sun_retrieval[2]
        labely = "Number of sun hits H channel"
        vmin = 0
        vmax = np.max(sun_retrieval[2]) + 1
    elif data_type == "el_width_h":
        value = sun_retrieval[3]
        labely = "Elevation beamwidth H channel (Deg)"
        vmin = 0.0
        vmax = 4.0
    elif data_type == "az_width_h":
        value = sun_retrieval[4]
        labely = "Azimuth beamwidth H channel (Deg)"
        vmin = 0.0
        vmax = 4.0
    elif data_type == "el_bias_h":
        value = sun_retrieval[5]
        ref = np.zeros(len(value))
        labely = "Elevation pointing bias H channel (Deg)"
        vmin = -2.0
        vmax = 2.0
    elif data_type == "az_bias_h":
        value = sun_retrieval[6]
        ref = np.zeros(len(value))
        labely = "Azimuth pointing bias H channel (Deg)"
        vmin = -2.0
        vmax = 2.0
    elif data_type == "dBm_sun_est":
        value = sun_retrieval[7]
        value_std = sun_retrieval[8]
        labely = "Sun Power H channel (dBm)"
        vmin = -110.0
        vmax = -90.0
    elif data_type == "rx_bias_h":
        value = 10.0 * np.ma.log10(sun_retrieval[9]) - 10.0 * np.ma.log10(
            sun_retrieval[21]
        )
        value_std = sun_retrieval[8]
        ref = np.zeros(len(value))
        labely = "Receiver bias H channel (dB)"
        vmin = -5.0
        vmax = 5.0
    elif data_type == "sf_h":
        value = 10.0 * np.ma.log10(sun_retrieval[9])
        # value_std = sun_retrieval[8]
        ref = 10.0 * np.ma.log10(sun_retrieval[21])
        labely = "Observed solar flux H channel (dB(sfu))"
        vmin = 15.0
        vmax = 30.0
    elif data_type == "nhits_v":
        value = sun_retrieval[10]
        labely = "Number of sun hits V channel"
        vmin = 0
        vmax = np.max(sun_retrieval[10]) + 1
    elif data_type == "el_width_v":
        value = sun_retrieval[11]
        labely = "Elevation beamwidth V channel (Deg)"
        vmin = 0.0
        vmax = 4.0
    elif data_type == "az_width_v":
        value = sun_retrieval[12]
        labely = "Azimuth beamwidth V channel (Deg)"
        vmin = 0.0
        vmax = 4.0
    elif data_type == "el_bias_v":
        value = sun_retrieval[13]
        ref = np.zeros(len(value))
        labely = "Elevation pointing bias V channel (Deg)"
        vmin = -2.0
        vmax = 2.0
    elif data_type == "az_bias_v":
        value = sun_retrieval[14]
        ref = np.zeros(len(value))
        labely = "Azimuth pointing bias V channel (Deg)"
        vmin = -2.0
        vmax = 2.0
    elif data_type == "dBmv_sun_est":
        value = sun_retrieval[15]
        value_std = sun_retrieval[16]
        labely = "Sun Power V channel (dBm)"
        vmin = -110.0
        vmax = -90.0
    elif data_type == "rx_bias_v":
        value = 10.0 * np.ma.log10(sun_retrieval[17]) - 10.0 * np.ma.log10(
            sun_retrieval[21]
        )
        value_std = sun_retrieval[16]
        ref = np.zeros(len(value))
        labely = "Receiver bias V channel (dB)"
        vmin = -5.0
        vmax = 5.0
    elif data_type == "sf_v":
        value = 10.0 * np.ma.log10(sun_retrieval[17])
        # value_std = sun_retrieval[16]
        ref = 10.0 * np.ma.log10(sun_retrieval[21])
        labely = "Observed solar flux V channel (dB(sfu))"
        vmin = 15.0
        vmax = 30.0
    elif data_type == "nhits_zdr":
        value = sun_retrieval[18]
        labely = "Number of sun hits ZDR"
        vmin = 0
        vmax = np.max(sun_retrieval[18]) + 1
    elif data_type == "ZDR_sun_est":
        value = sun_retrieval[19]
        value_std = sun_retrieval[20]
        ref = np.zeros(len(value))
        labely = "Sun ZDR (dB)"
        vmin = -2.0
        vmax = 2.0

    mask = np.ma.getmaskarray(value)
    if mask.all():
        warn("Unable to create figure " + " ".join(fname_list) + ". No valid data")
        return None

    # plot only valid data (but keep first and last date)
    isvalid = np.logical_not(mask)
    date2 = np.array(date)

    value_plt = value[isvalid]
    date_plt = date2[isvalid]
    if not isvalid[0]:
        value_plt = np.ma.append(np.ma.masked, value_plt)
        date_plt = np.ma.append(date2[0], date_plt)
    if not isvalid[-1]:
        value_plt = np.ma.append(value_plt, np.ma.masked)
        date_plt = np.ma.append(date_plt, date2[-1])

    fig, ax = plt.subplots(figsize=[10, 6], dpi=dpi)
    ax.plot(date_plt, value_plt, "x-")
    if value_std is not None:
        value_std_plt = value_std[isvalid]
        if not isvalid[0]:
            value_std_plt = np.ma.append(np.ma.masked, value_std_plt)
        if not isvalid[-1]:
            value_std_plt = np.ma.append(value_std_plt, np.ma.masked)

        ax.plot(date_plt, value_plt + value_std_plt, "rx-")
        ax.plot(date_plt, value_plt - value_std_plt, "rx-")
    if ref is not None:
        ref_plt = ref[isvalid]
        if not isvalid[0]:
            ref_plt = np.ma.append(ref[0], ref_plt)
        if not isvalid[-1]:
            ref_plt = np.ma.append(ref_plt, ref[-1])
        ax.plot(date_plt, ref_plt, "k--")
    ax.set_xlabel(labelx)
    ax.set_ylabel(labely)
    ax.set_title(titl)
    ax.set_ylim([vmin, vmax])
    ax.set_xlim([date_plt[0], date_plt[-1]])
    # tight x axis
    ax.autoscale(enable=True, axis="x", tight=True)
    ax.grid(True)

    # rotates and right aligns the x labels, and moves the bottom of the
    # axes up to make room for them
    fig.autofmt_xdate()

    for fname in fname_list:
        fig.savefig(fname, dpi=dpi)
    plt.close(fig)

    return fname_list
