def plot_waterxml_timeseries_comparison(waterxml_tree1,
                                        waterxml_tree2,
                                        is_visible=False,
                                        save_path=None):
    """   
    Compare each timeseries for 2 WATER \*.xml files.
    
    Parameters
    ----------
    waterxml_data1 : dictionary 
        A dictionary containing data found in WATER \*.xml data file.
    waterxml_data2 : dictionary 
        A dictionary containing data found in WATER \*.xml data file.
    is_visible : bool
        Boolean value to show plots         
    save_path : string 
        String path to save plot(s)      
    """
    project1, study1, simulation1 = waterxml.get_xml_data(
        waterxml_tree=waterxml_tree1)
    project2, study2, simulation2 = waterxml.get_xml_data(
        waterxml_tree=waterxml_tree2)

    assert len(simulation1["SimulID"]) == len(
        simulation2["SimulID"]
    ), "The lengths of the number of SimulID's between the 2 xml files are not equal."

    for i in range(len(simulation1["SimulID"])):
        for timeseries_str in [
                "StudyUnitDischargeSeries", "ClimaticPrecipitationSeries",
                "ClimaticTemperatureSeries"
        ]:

            region_type1 = simulation1["RegionType"][i]
            sim_id1 = simulation1["SimulID"][i]

            region_type2 = simulation2["RegionType"][i]
            sim_id2 = simulation2["SimulID"][i]

            # get the dates, values, and units - these are lists each of which contain arrays corresponding to each SimulID
            dates1, values1, units1 = waterxml.get_timeseries_data(
                simulation_dict=simulation1, timeseries_key=timeseries_str)
            dates2, values2, units2 = waterxml.get_timeseries_data(
                simulation_dict=simulation2, timeseries_key=timeseries_str)

            assert region_type1 == region_type2, "Region Types {} and {} are not equal".format(
                region_type1, region_type2)
            assert sim_id1 == sim_id2, "Simulation Id's {} and {} are not equal".format(
                sim_id1, sim_id2)
            assert units1[i] == units2[
                i], "Units {} and {} are not equal".format(
                    units1[i], units2[i])
            assert len(dates1[i]) == len(
                dates2[i]), "Length of dates {} and {} are not equal".format(
                    dates1[i], dates2[i])
            assert len(values1[i]) == len(
                values2[i]), "Length of values {} and {} are not equal".format(
                    values1[i], values2[i])

            fig = plt.figure(figsize=(12, 10))
            ax1 = fig.add_subplot(211)
            ax1.grid(True)

            if timeseries_str == "StudyUnitDischargeSeries":
                ylabel = "Discharge ({})".format(units1[i])
                color_str1 = "b"
                color_str2 = "r"

            elif timeseries_str == "ClimaticPrecipitationSeries":
                ylabel = "Precipitation ({})".format(units1[i])
                color_str1 = "SkyBlue"
                color_str2 = "r"

            elif timeseries_str == "ClimaticTemperatureSeries":
                ylabel = "Temperature ({})".format(units1[i])
                color_str1 = "orange"
                color_str2 = "r"
            else:
                ylabel = "Some other parameter"
                color_str1 = "k"
                color_str2 = "r"

            ax1.set_title("{}\nRegion Type: {}\nSimulation ID: {}".format(
                timeseries_str, region_type1, sim_id1))
            ax1.set_xlabel("Date")
            ax1.set_ylabel(ylabel)

            ax1.plot(dates1[i],
                     values1[i],
                     color=color_str1,
                     label=ylabel + " " + project1["ProjName"],
                     linewidth=2)
            ax1.hold(True)
            ax1.plot(dates2[i],
                     values2[i],
                     color=color_str2,
                     label=ylabel + " " + project2["ProjName"],
                     linewidth=2,
                     alpha=0.6)

            # increase y axis to have text and legend show up better
            curr_ylim = ax1.get_ylim()
            ax1.set_ylim((curr_ylim[0], curr_ylim[1] * 1.5))

            # rotate and align the tick labels so they look better
            fig.autofmt_xdate()

            # use a more precise date string for the x axis locations in the
            # toolbar
            ax1.fmt_xdata = mdates.DateFormatter("%Y-%m-%d")

            # legend; make it transparent
            handles1, labels1 = ax1.get_legend_handles_labels()
            legend1 = ax1.legend(handles1, labels1, fancybox=True)
            legend1.get_frame().set_alpha(0.5)
            legend1.draggable(state=True)

            # show text of mean, max, min values on graph; use matplotlib.patch.Patch properies and bbox
            text1 = "mean = %.2f\nmax = %.2f\nmin = %.2f\n---\nmean = %.2f\nmax = %.2f\nmin = %.2f" % (
                np.nanmean(values1[i]), np.nanmax(
                    values1[i]), np.nanmin(values1[i]), np.nanmean(values2[i]),
                np.nanmax(values2[i]), np.nanmin(values2[i]))
            patch_properties = {
                "boxstyle": "round",
                "facecolor": "wheat",
                "alpha": 0.5
            }

            ax1.text(0.05,
                     0.95,
                     text1,
                     transform=ax1.transAxes,
                     fontsize=14,
                     verticalalignment="top",
                     horizontalalignment="left",
                     bbox=patch_properties)

            # plot difference = values_b - values_a
            ax2 = fig.add_subplot(212, sharex=ax1)
            ax2.grid(True)
            ax2.set_title('Difference: ' + timeseries_str)
            ax2.set_xlabel('Date')
            ax2.set_ylabel('Difference' + ' (' + units1[i] + ')')
            diff = values2[i] - values1[i]
            ax2.plot(dates1[i], diff, color='k', linewidth=2)

            # increase y axis to have text and legend show up better
            curr_ylim2 = ax2.get_ylim()
            ax2.set_ylim((curr_ylim2[0], curr_ylim2[1] * 1.5))

            # use a more precise date string for the x axis locations in the toolbar
            ax2.fmt_xdata = mdates.DateFormatter('%Y-%m-%d')

            # show text of mean, max, min values on graph; use matplotlib.patch.Patch properies and bbox
            text2 = "mean = %.2f\nmax = %.2f\nmin = %.2f\n" % (
                np.nanmean(diff), np.nanmax(diff), np.nanmin(diff))

            ax2.text(0.05,
                     0.95,
                     text2,
                     transform=ax2.transAxes,
                     fontsize=14,
                     verticalalignment="top",
                     horizontalalignment="left",
                     bbox=patch_properties)

            # rotate and align the tick labels so they look better; note that ax2 will
            # have the dates, but ax1 will not. do not need to rotate each individual axis
            # because this method does it
            fig.autofmt_xdate()

            # save plots
            if save_path:
                # set the size of the figure to be saved
                curr_fig = plt.gcf()
                curr_fig.set_size_inches(12, 10)

                # split the parameter name to not include units because some units contain / character which Python interprets as an escape character
                filename = "-".join([
                    project1["ProjName"], "vs", project2["ProjName"],
                    timeseries_str, region_type1, sim_id1
                ]) + ".png"

                filepath = os.path.join(save_path, filename)
                plt.savefig(filepath, dpi=100)

            # show plots
            if is_visible:
                plt.show()
            else:
                plt.close()
def plot_waterxml_timeseries_comparison(waterxml_tree1, waterxml_tree2, is_visible = False, save_path = None):
    """   
    Compare each timeseries for 2 WATER \*.xml files.
    
    Parameters
    ----------
    waterxml_data1 : dictionary 
        A dictionary containing data found in WATER \*.xml data file.
    waterxml_data2 : dictionary 
        A dictionary containing data found in WATER \*.xml data file.
    is_visible : bool
        Boolean value to show plots         
    save_path : string 
        String path to save plot(s)      
    """
    project1, study1, simulation1 = waterxml.get_xml_data(waterxml_tree = waterxml_tree1)       
    project2, study2, simulation2 = waterxml.get_xml_data(waterxml_tree = waterxml_tree2)

    assert len(simulation1["SimulID"]) == len(simulation2["SimulID"]), "The lengths of the number of SimulID's between the 2 xml files are not equal."

    for i in range(len(simulation1["SimulID"])):
        for timeseries_str in ["StudyUnitDischargeSeries", "ClimaticPrecipitationSeries", "ClimaticTemperatureSeries"]:         

            region_type1 = simulation1["RegionType"][i]
            sim_id1 = simulation1["SimulID"][i]

            region_type2 = simulation2["RegionType"][i]
            sim_id2 = simulation2["SimulID"][i]

            # get the dates, values, and units - these are lists each of which contain arrays corresponding to each SimulID 
            dates1, values1, units1 = waterxml.get_timeseries_data(simulation_dict = simulation1, timeseries_key = timeseries_str)
            dates2, values2, units2 = waterxml.get_timeseries_data(simulation_dict = simulation2, timeseries_key = timeseries_str)

            assert region_type1 == region_type2, "Region Types {} and {} are not equal".format(region_type1, region_type2)
            assert sim_id1 == sim_id2, "Simulation Id's {} and {} are not equal".format(sim_id1, sim_id2)
            assert units1[i] == units2[i], "Units {} and {} are not equal".format(units1[i], units2[i])            
            assert len(dates1[i]) == len(dates2[i]), "Length of dates {} and {} are not equal".format(dates1[i], dates2[i]) 
            assert len(values1[i]) == len(values2[i]), "Length of values {} and {} are not equal".format(values1[i], values2[i]) 
               
            fig = plt.figure(figsize=(12,10))
            ax1 = fig.add_subplot(211)
            ax1.grid(True)

            if timeseries_str == "StudyUnitDischargeSeries":
                ylabel = "Discharge ({})".format(units1[i])
                color_str1 = "b"
                color_str2 = "r"  
                
            elif timeseries_str == "ClimaticPrecipitationSeries":
                ylabel = "Precipitation ({})".format(units1[i])
                color_str1 = "SkyBlue"      
                color_str2 = "r"  
                
            elif timeseries_str == "ClimaticTemperatureSeries":
                ylabel = "Temperature ({})".format(units1[i])
                color_str1 = "orange"  
                color_str2 = "r"                 
            else:
                ylabel = "Some other parameter"
                color_str1 = "k" 
                color_str2 = "r" 
                
            ax1.set_title("{}\nRegion Type: {}\nSimulation ID: {}".format(timeseries_str, region_type1, sim_id1))
            ax1.set_xlabel("Date")
            ax1.set_ylabel(ylabel)   
            
            ax1.plot(dates1[i], values1[i], color = color_str1, label = ylabel + " " + project1["ProjName"], linewidth = 2) 
            ax1.hold(True)
            ax1.plot(dates2[i], values2[i], color = color_str2, label = ylabel + " " + project2["ProjName"], linewidth = 2, alpha = 0.6)
            
            # increase y axis to have text and legend show up better
            curr_ylim = ax1.get_ylim()
            ax1.set_ylim((curr_ylim[0], curr_ylim[1] * 1.5))
    
            # rotate and align the tick labels so they look better
            fig.autofmt_xdate()
            
            # use a more precise date string for the x axis locations in the
            # toolbar
            ax1.fmt_xdata = mdates.DateFormatter("%Y-%m-%d")
         
            # legend; make it transparent    
            handles1, labels1 = ax1.get_legend_handles_labels()
            legend1 = ax1.legend(handles1, labels1, fancybox = True)
            legend1.get_frame().set_alpha(0.5)
            legend1.draggable(state=True)
            
            # show text of mean, max, min values on graph; use matplotlib.patch.Patch properies and bbox
            text1 = "mean = %.2f\nmax = %.2f\nmin = %.2f\n---\nmean = %.2f\nmax = %.2f\nmin = %.2f" % (np.nanmean(values1[i]), np.nanmax(values1[i]), np.nanmin(values1[i]), np.nanmean(values2[i]), np.nanmax(values2[i]), np.nanmin(values2[i]))
            patch_properties = {"boxstyle": "round", "facecolor": "wheat", "alpha": 0.5}
                           
            ax1.text(0.05, 0.95, text1, transform = ax1.transAxes, fontsize = 14, 
                    verticalalignment = "top", horizontalalignment = "left", bbox = patch_properties)
 
            # plot difference = values_b - values_a
            ax2 = fig.add_subplot(212, sharex = ax1)
            ax2.grid(True)
            ax2.set_title('Difference: ' + timeseries_str)
            ax2.set_xlabel('Date')
            ax2.set_ylabel('Difference' + ' (' + units1[i] + ')')
            diff = values2[i] - values1[i]
            ax2.plot(dates1[i], diff, color = 'k', linewidth = 2)  

            # increase y axis to have text and legend show up better
            curr_ylim2 = ax2.get_ylim()
            ax2.set_ylim((curr_ylim2[0], curr_ylim2[1] * 1.5))
            
            # use a more precise date string for the x axis locations in the toolbar
            ax2.fmt_xdata = mdates.DateFormatter('%Y-%m-%d')

            # show text of mean, max, min values on graph; use matplotlib.patch.Patch properies and bbox
            text2 = "mean = %.2f\nmax = %.2f\nmin = %.2f\n" % (np.nanmean(diff), np.nanmax(diff), np.nanmin(diff))
                           
            ax2.text(0.05, 0.95, text2, transform = ax2.transAxes, fontsize = 14, 
                    verticalalignment = "top", horizontalalignment = "left", bbox = patch_properties)
           
            # rotate and align the tick labels so they look better; note that ax2 will 
            # have the dates, but ax1 will not. do not need to rotate each individual axis
            # because this method does it
            fig.autofmt_xdate()
           
            # save plots
            if save_path:        
                # set the size of the figure to be saved
                curr_fig = plt.gcf()
                curr_fig.set_size_inches(12, 10)
                
                # split the parameter name to not include units because some units contain / character which Python interprets as an escape character
                filename = "-".join([project1["ProjName"], "vs", project2["ProjName"], timeseries_str, region_type1, sim_id1])  + ".png" 
         
                filepath = os.path.join(save_path, filename)
                plt.savefig(filepath, dpi = 100)                                          
                        
            # show plots
            if is_visible:
                plt.show()
            else:
                plt.close()
def plot_waterxml_timeseries_data(waterxml_tree,
                                  is_visible=False,
                                  save_path=None):
    """   
    Plot timeseries data from the WATER \*.xml file.  The timeseries data are contained 
    in the study simulation dictionary. The following timeseries data are plotted:
    discharge - from xml element called "StudyUnitDischargeSeries", 
    precipitation - from xml element called "ClimaticPrecipitationSeries",
    temperature = from xml element called "ClimaticTemperatureSeries"
    
    Parameters
    ----------
    waterxml_data : dictionary 
        A dictionary containing data found in WATER \*.xml data file.
    is_visible : bool
        Boolean value to show plots         
    save_path : string 
        String path to save plot(s)      
    """
    project, study, simulation = waterxml.get_xml_data(
        waterxml_tree=waterxml_tree)

    for i in range(len(simulation["SimulID"])):
        for timeseries_str in [
                "StudyUnitDischargeSeries", "ClimaticPrecipitationSeries",
                "ClimaticTemperatureSeries"
        ]:

            region_type = simulation["RegionType"][i]
            sim_id = simulation["SimulID"][i]

            # get the dates, values, and units - these are lists each of which contain arrays corresponding to each SimulID
            dates, values, units = waterxml.get_timeseries_data(
                simulation_dict=simulation, timeseries_key=timeseries_str)

            fig = plt.figure(figsize=(12, 10))
            ax = fig.add_subplot(111)
            ax.grid(True)

            if timeseries_str == "StudyUnitDischargeSeries":
                ylabel = "Discharge ({})".format(units[i])
                color_str = "b"

            elif timeseries_str == "ClimaticPrecipitationSeries":
                ylabel = "Precipitation ({})".format(units[i])
                color_str = "SkyBlue"

            elif timeseries_str == "ClimaticTemperatureSeries":
                ylabel = "Temperature ({})".format(units[i])
                color_str = "orange"

            else:
                ylabel = "Some other parameter"
                color_str = "k"

            ax.set_title("{}\nRegion Type: {}\nSimulation ID: {}".format(
                timeseries_str, region_type, sim_id))
            ax.set_xlabel("Date")
            ax.set_ylabel(ylabel)

            plt.plot(dates[i], values[i], color=color_str, label=ylabel)

            # rotate and align the tick labels so they look better
            fig.autofmt_xdate()

            # use a more precise date string for the x axis locations in the
            # toolbar
            ax.fmt_xdata = mdates.DateFormatter("%Y-%m-%d")

            # legend; make it transparent
            handles, labels = ax.get_legend_handles_labels()
            legend = ax.legend(handles, labels, fancybox=True)
            legend.get_frame().set_alpha(0.5)
            legend.draggable(state=True)

            # show text of mean, max, min values on graph; use matplotlib.patch.Patch properies and bbox
            text = "mean = %.2f\nmax = %.2f\nmin = %.2f" % (np.nanmean(
                values[i]), np.nanmax(values[i]), min(values[i]))
            patch_properties = {
                "boxstyle": "round",
                "facecolor": "wheat",
                "alpha": 0.5
            }

            ax.text(0.05,
                    0.95,
                    text,
                    transform=ax.transAxes,
                    fontsize=14,
                    verticalalignment="top",
                    horizontalalignment="left",
                    bbox=patch_properties)

            # save plots
            if save_path:
                # set the size of the figure to be saved
                curr_fig = plt.gcf()
                curr_fig.set_size_inches(12, 10)

                # split the parameter name to not include units because some units contain / character which Python interprets as an escape character
                filename = "-".join([
                    project["UserName"], project["ProjName"], timeseries_str,
                    region_type, sim_id
                ]) + ".png"
                filepath = os.path.join(save_path, filename)
                plt.savefig(filepath, dpi=100)

            # show plots
            if is_visible:
                plt.show()
            else:
                plt.close()
def plot_waterxml_timeseries_data(waterxml_tree, is_visible = False, save_path = None):
    """   
    Plot timeseries data from the WATER \*.xml file.  The timeseries data are contained 
    in the study simulation dictionary. The following timeseries data are plotted:
    discharge - from xml element called "StudyUnitDischargeSeries", 
    precipitation - from xml element called "ClimaticPrecipitationSeries",
    temperature = from xml element called "ClimaticTemperatureSeries"
    
    Parameters
    ----------
    waterxml_data : dictionary 
        A dictionary containing data found in WATER \*.xml data file.
    is_visible : bool
        Boolean value to show plots         
    save_path : string 
        String path to save plot(s)      
    """
    project, study, simulation = waterxml.get_xml_data(waterxml_tree = waterxml_tree)       

    for i in range(len(simulation["SimulID"])):
        for timeseries_str in ["StudyUnitDischargeSeries", "ClimaticPrecipitationSeries", "ClimaticTemperatureSeries"]:         

            region_type = simulation["RegionType"][i]
            sim_id = simulation["SimulID"][i]

            # get the dates, values, and units - these are lists each of which contain arrays corresponding to each SimulID 
            dates, values, units = waterxml.get_timeseries_data(simulation_dict = simulation, timeseries_key = timeseries_str)

            fig = plt.figure(figsize=(12,10))
            ax = fig.add_subplot(111)
            ax.grid(True)

            if timeseries_str == "StudyUnitDischargeSeries":
                ylabel = "Discharge ({})".format(units[i])
                color_str = "b"
                
            elif timeseries_str == "ClimaticPrecipitationSeries":
                ylabel = "Precipitation ({})".format(units[i])
                color_str = "SkyBlue"      
                
            elif timeseries_str == "ClimaticTemperatureSeries":
                ylabel = "Temperature ({})".format(units[i])
                color_str = "orange"  
                
            else:
                ylabel = "Some other parameter"
                color_str = "k" 
            
            ax.set_title("{}\nRegion Type: {}\nSimulation ID: {}".format(timeseries_str, region_type, sim_id))
            ax.set_xlabel("Date")
            ax.set_ylabel(ylabel)   
            
            plt.plot(dates[i], values[i], color = color_str, label = ylabel) 
        
            # rotate and align the tick labels so they look better
            fig.autofmt_xdate()
            
            # use a more precise date string for the x axis locations in the
            # toolbar
            ax.fmt_xdata = mdates.DateFormatter("%Y-%m-%d")
         
            # legend; make it transparent    
            handles, labels = ax.get_legend_handles_labels()
            legend = ax.legend(handles, labels, fancybox = True)
            legend.get_frame().set_alpha(0.5)
            legend.draggable(state=True)
            
            # show text of mean, max, min values on graph; use matplotlib.patch.Patch properies and bbox
            text = "mean = %.2f\nmax = %.2f\nmin = %.2f" % (np.nanmean(values[i]), np.nanmax(values[i]), min(values[i]))
            patch_properties = {"boxstyle": "round", "facecolor": "wheat", "alpha": 0.5}
                           
            ax.text(0.05, 0.95, text, transform = ax.transAxes, fontsize = 14, 
                    verticalalignment = "top", horizontalalignment = "left", bbox = patch_properties)
            
            # save plots
            if save_path:        
                # set the size of the figure to be saved
                curr_fig = plt.gcf()
                curr_fig.set_size_inches(12, 10)
                
                # split the parameter name to not include units because some units contain / character which Python interprets as an escape character
                filename = "-".join([project["UserName"], project["ProjName"], timeseries_str, region_type, sim_id])  + ".png"           
                filepath = os.path.join(save_path, filename)
                plt.savefig(filepath, dpi = 100)                        
              
            # show plots
            if is_visible:
                plt.show()
            else:
                plt.close()