def plot_residual_histogram(values, path_result, name_fig):
    """Plot residuals as histogram and test for normal distribution

    https://matplotlib.org/1.2.1/examples/pylab_examples/histogram_demo.html
    https://stackoverflow.com/questions/22179119/normality-test-of-a-distribution-in-python
    """
    plt.figure(facecolor="white")

    # Sort according to size
    values.sort()

    # the histogram of the data
    n, bins, patches = plt.hist(
        values,
        50,
        normed=1,
        facecolor='grey')

    # ------------------
    # Plot normal distribution
    # ------------------
    mu = np.average(values)
    sigma = np.std(values)
    plt.plot(
        bins,
        mlab.normpdf(bins, mu, sigma),
        color='r')

    # -----------
    # Test for normal distribution
    # https://stackoverflow.com/questions/12838993/scipy-normaltest-how-is-it-used
    # http://www.socscistatistics.com/pvalues/chidistribution.aspx
    # http://stattrek.com/chi-square-test/goodness-of-fit.aspx?Tutorial=AP
    # -----------
    chi_squared, p_value = stats.normaltest(values)

    # ---------------
    # plot histogram
    # ---------------
    font_additional_info = plotting_styles.font_info()

    plt.xlabel('Smarts')
    plt.ylabel('Probability')
    plt.title("Residual distribution (chi_squared: {}  p_value:  {}".format(
        round(chi_squared, 4),
        round(p_value, 4)),
        fontsize=10,
        fontdict=font_additional_info,
        loc='right')
    #plt.grid(True)

    #Save fig
    plt.savefig(os.path.join(path_result, name_fig))
def plot_tot_fueltype_y_over_time(scenario_data,
                                  fueltypes,
                                  fueltypes_to_plot,
                                  fig_name,
                                  txt_name,
                                  plotshow=False):
    """Plot total demand over simulation period for every
    scenario for all regions
    """
    results_txt = []

    # Set figure size
    fig = plt.figure(figsize=basic_plot_functions.cm2inch(9, 8))

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

    y_scenario = {}

    for scenario_name, scen_data in scenario_data.items():

        # Read out fueltype specific max h load
        data_years = {}
        for year, fueltype_reg_time in scen_data['ed_fueltype_regs_yh'].items(
        ):

            # Sum all regions
            tot_gwh_fueltype_yh = np.sum(fueltype_reg_time, axis=1)

            # Sum all hours
            tot_gwh_fueltype_y = np.sum(tot_gwh_fueltype_yh, axis=1)

            # Convert to TWh
            tot_gwh_fueltype_y = conversions.gwh_to_twh(tot_gwh_fueltype_y)

            data_years[year] = tot_gwh_fueltype_y

        y_scenario[scenario_name] = data_years

    # -----------------
    # Axis
    # -----------------
    base_yr, year_interval = 2020, 10
    first_scen = list(y_scenario.keys())[0]
    end_yr = list(y_scenario[first_scen].keys())

    major_ticks = np.arange(base_yr, end_yr[-1] + year_interval, year_interval)

    plt.xticks(major_ticks, major_ticks)

    # ----------
    # Plot lines
    # ----------
    #color_list_selection_fueltypes = plotting_styles.color_list_selection()
    color_list_selection = plotting_styles.color_list_scenarios()
    linestyles = ['--', '-', ':', "-.",
                  ".-"]  #linestyles = plotting_styles.linestyles()

    cnt_scenario = -1
    for scenario_name, fuel_fueltype_yrs in y_scenario.items():
        cnt_scenario += 1
        color = color_list_selection[cnt_scenario]
        cnt_linestyle = -1

        for fueltype_str, fueltype_nr in fueltypes.items():

            if fueltype_str in fueltypes_to_plot:
                cnt_linestyle += 1
                # Get fuel per fueltpye for every year
                fuel_fueltype = []
                for entry in list(fuel_fueltype_yrs.values()):
                    fuel_fueltype.append(entry[fueltype_nr])

                plt.plot(
                    list(fuel_fueltype_yrs.keys()),  # years
                    fuel_fueltype,  # yearly data per fueltype
                    color=color,
                    linestyle=linestyles[cnt_linestyle],
                    label="{}_{}".format(scenario_name, fueltype_str))

                # ---
                # Calculate difference in demand from 2015 - 2050
                # ---
                tot_2015 = fuel_fueltype[0]
                tot_2050 = fuel_fueltype[-1]
                diff_abs = tot_2050 - tot_2015
                p_diff_2015_2015 = ((100 / tot_2015) * tot_2050) - 100  # Diff

                txt = "fueltype_str: {} ed_tot_by: {} ed_tot_cy: {}, diff_p: {}, diff_abs: {} scenario: {}".format(
                    fueltype_str, round(tot_2015, 1), round(tot_2050, 1),
                    round(p_diff_2015_2015, 1), round(diff_abs, 1),
                    scenario_name)

                results_txt.append(txt)

    # --------------------------
    # Save model results to txt
    # --------------------------
    write_data.write_list_to_txt(txt_name, results_txt)

    # ----
    # Axis
    # ----
    plt.ylim(ymin=0)

    # ------------
    # Plot legend
    # ------------
    ax.legend(ncol=2,
              frameon=False,
              loc='upper center',
              prop={
                  'family': 'arial',
                  'size': 4
              },
              bbox_to_anchor=(0.5, -0.1))

    # ---------
    # Labels
    # ---------
    font_additional_info = plotting_styles.font_info(size=5)

    plt.ylabel("TWh")
    plt.xlabel("year")

    # Tight layout
    plt.tight_layout()
    plt.margins(x=0)

    plt.savefig(fig_name)

    if plotshow:
        plt.show()

    plt.close()
def plot_reg_y_over_time(scenario_data, fig_name, plotshow=False):
    """Plot total demand over simulation period for every
    scenario for all regions
    """
    # Set figure size
    plt.figure(figsize=basic_plot_functions.cm2inch(14, 8))

    y_scenario = {}

    for scenario_name, scen_data in scenario_data.items():

        data_years_regs = {}
        for year, fueltype_reg_time in scen_data['ed_fueltype_regs_yh'].items(
        ):
            data_years_regs[year] = {}

            for _fueltype, regions_fuel in enumerate(fueltype_reg_time):
                for region_nr, region_fuel in enumerate(regions_fuel):

                    # Sum all regions and fueltypes
                    reg_gwh_fueltype_y = np.sum(region_fuel)

                    try:
                        data_years_regs[year][region_nr] += reg_gwh_fueltype_y
                    except:
                        data_years_regs[year][region_nr] = reg_gwh_fueltype_y

        y_scenario[scenario_name] = data_years_regs

    # -----------------
    # Axis
    # -----------------
    base_yr, year_interval = 2015, 5
    first_scen = list(y_scenario.keys())[0]
    end_yr = list(y_scenario[first_scen].keys())[-1]

    major_ticks = np.arange(base_yr, end_yr + year_interval, year_interval)

    plt.xticks(major_ticks, major_ticks)

    # ----------
    # Plot lines
    # ----------
    color_list_selection = plotting_styles.color_list_scenarios()
    cnt = -1
    for scenario_name, fuel_fueltype_yrs in y_scenario.items():

        cnt += 1

        color_scenario = color_list_selection[cnt]

        for year, regs in fuel_fueltype_yrs.items():
            nr_of_reg = len(regs.keys())
            break

        for reg_nr in range(nr_of_reg):
            reg_data = []
            for year, regions_fuel in fuel_fueltype_yrs.items():
                reg_data.append(regions_fuel[reg_nr])

            plt.plot(list(fuel_fueltype_yrs.keys()),
                     list(reg_data),
                     label="{}".format(scenario_name),
                     color=str(color_scenario))
    # ----
    # Axis
    # ----
    plt.ylim(ymin=0)

    # ------------
    # Plot legend
    # ------------
    '''plt.legend(
        ncol=2,
        loc=3,
        prop={
            'family': 'arial',
            'size': 10},
        frameon=False)'''

    # ---------
    # Labels
    # ---------
    font_additional_info = plotting_styles.font_info(size=5)

    plt.ylabel("GWh")
    plt.xlabel("year")
    plt.title("tot_y", fontdict=font_additional_info)

    # Tight layout
    plt.tight_layout()
    plt.margins(x=0)

    plt.savefig(fig_name)

    if plotshow:
        plt.show()
        plt.close()
    else:
        plt.close()
def plot_radar_plot_multiple_lines(dh_profiles,
                                   fig_name,
                                   plot_steps,
                                   scenario_names,
                                   plotshow=False,
                                   lf_y_by=None,
                                   lf_y_cy=None,
                                   list_diff_max_h=None):
    """Plot daily load profile on a radar plot

    Arguments
    ---------
    dh_profile : list
        Dh values to plot
    fig_name : str
        Path to save figure

    SOURCE: https://python-graph-gallery.com/390-basic-radar-chart/
    """
    fig = plt.figure(figsize=basic_plot_functions.cm2inch(9, 14))

    # Get maximum demand of all lines
    max_entry = 0
    for line_entries in dh_profiles:
        max_in_line = max(line_entries)
        if max_in_line > max_entry:
            max_entry = max_in_line

    max_demand = round(max_entry, -1) + 10  # Round to nearest 10 plus add 10

    nr_of_plot_steps = int(max_demand / plot_steps) + 1

    axis_plots_inner = []
    axis_plots_innter_position = []

    # --------------------
    # Ciruclar axis
    # --------------------
    for i in range(nr_of_plot_steps):
        axis_plots_inner.append(plot_steps * i)
        axis_plots_innter_position.append(str(plot_steps * i))

    # Minor ticks
    minor_tick_interval = plot_steps / 2
    minor_ticks = []
    for i in range(nr_of_plot_steps * 2):
        minor_ticks.append(minor_tick_interval * i)

    # ----
    # Select color scheme
    # ----

    # Colors with scenarios
    #color_scenarios = plotting_styles.color_list_scenarios() #Color scheme Fig 13

    # Colors for plotting Fig. 13
    #color_scenarios = plotting_styles.color_list_selection_dm() # Color scheme Fig 13

    # Color sheme multiple scenarios
    color_scenarios = ['orange', 'darkred', '#3b2c85',
                       '#85cfcb']  #Lines for Fig 12

    color_lines = ['black'] + color_scenarios
    #color_lines = color_scenarios
    years = ['2015', '2050']
    linewidth_list = [1.0, 0.7]
    linestyle_list = ['-', '--']
    scenario_names.insert(0, "any")

    # Iterate lines
    cnt = -1
    for dh_profile in dh_profiles:

        if cnt >= 0:
            cnt_year = 1
        else:
            cnt_year = 0
        cnt += 1

        # Line properties
        color_line = color_lines[cnt]
        year_line = years[cnt_year]

        data = {'dh_profile': ['testname']}

        # Key: Label outer circle
        for hour in range(24):
            data[hour] = dh_profile[hour]

        # Set data
        df = pd.DataFrame(data)

        # number of variable
        categories = list(df)[1:]
        N = len(categories)

        # We are going to plot the first line of the data frame.
        # But we need to repeat the first value to close the circular graph:
        values = df.loc[0].drop('dh_profile').values.flatten().tolist()
        values += values[:1]

        # What will be the angle of each axis in the plot? (we divide the plot / number of variable)
        angles = [n / float(N) * 2 * math.pi for n in range(N)]
        angles += angles[:1]

        # Initialise the spider plot
        ax = plt.subplot(111, polar=True)

        # Change axis properties
        ax.yaxis.grid(color='grey', linestyle=':', linewidth=0.4)
        ax.xaxis.grid(color='lightgrey', linestyle=':', linewidth=0.4)

        # Change to clockwise cirection
        ax.set_theta_direction(-1)

        # Set first hour on top
        ax.set_theta_zero_location("N")

        # Draw one axe per variable + add labels labels yet (numbers)
        plt.xticks(angles[:-1], categories, color='black', size=8)

        # Draw ylabels (numbers)
        ax.set_rlabel_position(0)

        # Working alternative
        plt.yticks(axis_plots_inner,
                   axis_plots_innter_position,
                   color="black",
                   size=8)

        #ax.set_yticks(axis_plots_inner, minor=False)
        #ax.tick_params(axis='y', pad=35)
        #ax.set_yticks(minor_ticks, minor=True) #Somehow not working

        # Set limit to size
        plt.ylim(0, max_demand)
        plt.ylim(0, nr_of_plot_steps * plot_steps)

        # Smooth lines
        angles_smoothed, values_smoothed = basic_plot_functions.smooth_data(
            angles, values, spider=True)

        # Plot data
        ax.plot(angles_smoothed,
                values_smoothed,
                color=color_line,
                linestyle=linestyle_list[cnt_year],
                linewidth=linewidth_list[cnt_year],
                label="{} {}".format(year_line, scenario_names[cnt]))

        # Radar area
        ax.fill(angles_smoothed, values_smoothed, color_line, alpha=0.05)

    # ------------
    # Write outs
    # ------------
    font_additional_info = plotting_styles.font_info(size=4)

    for cnt, entry in enumerate(list_diff_max_h):
        plt.text(0.15,
                 0 + cnt / 50,
                 entry,
                 fontsize=2,
                 fontdict=font_additional_info,
                 transform=plt.gcf().transFigure)

    # ------------
    # Legend
    # ------------
    plt.legend(ncol=1,
               bbox_to_anchor=(0.3, -0.05),
               prop={'size': 4},
               frameon=False)

    plt.savefig(fig_name)

    if plotshow:
        plt.show()

    plt.close()
def plot_LAD_comparison_scenarios(scenario_data,
                                  year_to_plot,
                                  fig_name,
                                  plotshow=True):
    """Plot chart comparing total annual demand for all LADs

    Arguments
    ---------
    scenario_data : dict
        Scenario name, scenario data
    year_to_plot : int
        Year to plot different LAD values
    fig_name : str
        Path to out pdf figure
    plotshow : bool
        Plot figure or not

    Info
    -----
    if scenario name starts with _ the legend does not work
    """

    # Get first scenario in dict
    all_scenarios = list(scenario_data.keys())
    first_scenario = str(all_scenarios[:1][0])

    # ----------------
    # Sort regions according to size
    # -----------------
    regions = {}
    for fueltype, fuels_regs in enumerate(
            scenario_data[first_scenario]['ed_fueltype_regs_yh'][2015]):

        for region_array_nr, fuel_reg in enumerate(fuels_regs):
            try:
                regions[region_array_nr] += np.sum(fuel_reg)
            except KeyError:
                regions[region_array_nr] = np.sum(fuel_reg)

    sorted_regions = sorted(regions.items(), key=operator.itemgetter(1))

    sorted_regions_nrs = []
    for sort_info in sorted_regions:
        sorted_regions_nrs.append(sort_info[0])

    # Labels
    labels = []
    for sorted_region in sorted_regions_nrs:
        geocode_lad = sorted_region  # If actual LAD name, change this
        labels.append(geocode_lad)

    # -------------------------------------
    # Plot
    # -------------------------------------
    fig = plt.figure(figsize=basic_plot_functions.cm2inch(9, 8))

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

    x_values = np.arange(0, len(sorted_regions_nrs), 1)

    # ----------------------------------------------
    # Plot base year values
    # ----------------------------------------------
    base_year_data = []
    for reg_array_nr in sorted_regions_nrs:
        base_year_data.append(regions[reg_array_nr])
    total_base_year_sum = sum(base_year_data)

    plt.plot(x_values,
             base_year_data,
             linestyle='None',
             marker='o',
             markersize=1.6,
             fillstyle='full',
             markerfacecolor='grey',
             markeredgewidth=0.4,
             color='black',
             label='actual_by ({})'.format(total_base_year_sum))

    # ----------------------------------------------
    # Plot all future scenario values
    # ----------------------------------------------
    color_list = plotting_styles.color_list()

    for scenario_nr, (scenario_name,
                      fuel_data) in enumerate(scenario_data.items()):

        sorted_year_data = []
        for reg_array_nr in sorted_regions_nrs:
            tot_fuel_across_fueltypes = 0
            for fueltype, fuel_regs in enumerate(
                    fuel_data['ed_fueltype_regs_yh'][year_to_plot]):
                tot_fuel_across_fueltypes += np.sum(fuel_regs[reg_array_nr])

            sorted_year_data.append(tot_fuel_across_fueltypes)

        tot_fuel_all_reg = np.sum(
            fuel_data['ed_fueltype_regs_yh'][year_to_plot])
        print("TOTAL FUEL in GWH " + str(tot_fuel_all_reg))

        # Calculate total annual demand
        tot_demand = sum(sorted_year_data)
        scenario_name = "{} (tot: {} [GWh])".format(scenario_name,
                                                    round(tot_demand, 2))

        plt.plot(x_values,
                 sorted_year_data,
                 linestyle='None',
                 marker='o',
                 markersize=1.6,
                 fillstyle='full',
                 markerfacecolor=color_list[scenario_nr],
                 markeredgewidth=0.4,
                 color=color_list[scenario_nr],
                 label=scenario_name)

    # --------
    # Axis
    # --------
    plt.tick_params(
        axis='x',  # changes apply to the x-axis
        which='both',  # both major and minor ticks are affected
        bottom='off',  # ticks along the bottom edge are off
        top='off',  # ticks along the top edge are off
        labelbottom='off')  # labels along the bottom edge are off

    # Limit
    plt.ylim(ymin=0)

    # -----------
    # Labelling
    # -----------
    label_points = False
    if label_points:
        for pos, txt in enumerate(labels):
            ax.text(x_values[pos],
                    sorted_year_data[pos],
                    txt,
                    horizontalalignment="right",
                    verticalalignment="top",
                    fontsize=3)

    plt.title("TEST", loc='left', fontdict=plotting_styles.font_info())

    plt.xlabel("UK regions (excluding northern ireland)")
    plt.ylabel("[GWh]")

    # --------
    # Legend
    # --------
    plt.legend(prop={'family': 'arial', 'size': 8}, frameon=False)

    # Tight layout
    plt.margins(x=0)
    plt.tight_layout()
    plt.savefig(fig_name)

    if plotshow:
        plt.show()
    else:
        plt.close()
def run(path_fig_folder,
        path_plot_fig,
        calc_av_lp_modelled,
        calc_av_lp_real,
        calc_lp_modelled=None,
        calc_lp_real=None,
        plot_peak=False,
        plot_radar=False,
        plot_all_entries=False,
        plot_max_min_polygon=True,
        plotshow=False,
        max_y_to_plot=60,
        fueltype_str=False,
        year=False):
    """Plotting average saisonal loads for each daytype. As an input
    GWh is provided, which for each h is cancelled out to GW.

    https://stackoverflow.com/questions/4325733/save-a-subplot-in-matplotlib
    http://matthiaseisen.com/matplotlib/shapes/reg-polygon/
    """
    fig = plt.figure(figsize=basic_plot_functions.cm2inch(14, 25))

    # ax = fig.add_subplot(nrows=4, ncols=2)

    plot_nr = 0
    row = -1
    for season in calc_av_lp_modelled:
        row += 1
        col = -1
        for daytype in calc_av_lp_modelled[season]:
            col += 1
            plot_nr += 1

            axes = plt.subplot(4, 2, plot_nr)

            # ------------------
            # Plot average
            # ------------------
            x_values = range(24)

            plt.plot(x_values,
                     list(calc_av_lp_real[season][daytype]),
                     color='black',
                     label='av_real or av by',
                     linestyle='--',
                     linewidth=0.5)

            plt.plot(x_values,
                     list(calc_av_lp_modelled[season][daytype]),
                     color='blue',
                     label='av_modelled or av cy',
                     linestyle='--',
                     linewidth=0.5)

            # --------------
            # Radar plots
            # --------------
            if plot_radar:
                name_spider_plot = os.path.join(
                    path_fig_folder,
                    "spider_{}_{}_{}_{}_.pdf".format(year, fueltype_str,
                                                     season, daytype))

                plot_radar_plot(list(calc_av_lp_modelled[season][daytype]),
                                name_spider_plot,
                                plot_steps=20,
                                plotshow=False)

            # ------------------
            # Plot every single line
            # ------------------
            if plot_all_entries:
                for entry in range(len(calc_lp_real[season][daytype])):
                    plt.plot(x_values,
                             list(calc_lp_real[season][daytype][entry]),
                             color='grey',
                             markersize=0.5,
                             alpha=0.2)

                    plt.plot(x_values,
                             list(calc_lp_modelled[season][daytype][entry]),
                             color='blue',
                             markersize=0.5,
                             alpha=0.2)

            # ----------
            # Plot max_min range polygons
            # ----------
            if plot_max_min_polygon:

                # ----Draw real
                min_max_polygon = []
                upper_boundary = []
                lower_bdoundary = []

                # Get min and max of all entries for hour
                for hour in range(24):
                    min_y = np.min(calc_lp_real[season][daytype][:, hour],
                                   axis=0)
                    max_y = np.max(calc_lp_real[season][daytype][:, hour],
                                   axis=0)
                    upper_boundary.append((hour, min_y))
                    lower_bdoundary.append((hour, max_y))

                # create correct sorting to draw filled polygon
                min_max_polygon = fig_lf.order_polygon(upper_boundary,
                                                       lower_bdoundary)
                #min_max_polygon = create_min_max_polygon_from_lines(reg_load_factor_y)

                polygon = plt.Polygon(min_max_polygon,
                                      color='grey',
                                      alpha=0.2,
                                      edgecolor=None,
                                      linewidth=0,
                                      fill='True')

                axes.add_patch(polygon)

                # -----Draw modelled
                min_max_polygon = []
                upper_boundary = []
                lower_bdoundary = []

                # Get min and max of all entries for hour
                for hour in range(24):
                    min_y = np.min(calc_lp_modelled[season][daytype][:, hour],
                                   axis=0)
                    max_y = np.max(calc_lp_modelled[season][daytype][:, hour],
                                   axis=0)
                    upper_boundary.append((hour, min_y))
                    lower_bdoundary.append((hour, max_y))

                # create correct sorting to draw filled polygon
                min_max_polygon = fig_lf.order_polygon(upper_boundary,
                                                       lower_bdoundary)

                polygon = plt.Polygon(min_max_polygon,
                                      color='blue',
                                      alpha=0.2,
                                      edgecolor=None,
                                      linewidth=0,
                                      fill='True')

                axes.add_patch(polygon)

            # --------------------
            # Get load shape within season with highest houly load
            # --------------------
            if plot_peak:

                # Get row with maximum hourly value
                day_with_max_h = np.argmax(
                    np.max(calc_lp_real[season][daytype], axis=1))

                plt.plot(x_values,
                         list(calc_lp_real[season][daytype][day_with_max_h]),
                         color='grey',
                         markersize=1.0,
                         label='real_peak or by peak',
                         linestyle='-.',
                         linewidth=0.5)

                # Get row with maximum hourly value
                day_with_max_h = np.argmax(
                    np.max(calc_lp_modelled[season][daytype], axis=1))

                plt.plot(
                    x_values,
                    list(calc_lp_modelled[season][daytype][day_with_max_h]),
                    color='blue',
                    markersize=1.0,
                    label='modelled_peak or cy peak',
                    linestyle='-.',
                    linewidth=0.5)

            # -----------------
            # Axis
            # -----------------
            plt.ylim(0, max_y_to_plot)
            plt.xlim(0, 23)

            # Tight layout
            plt.tight_layout()
            plt.margins(x=0)

            # Calculate RMSE
            rmse = basic_functions.rmse(calc_av_lp_modelled[season][daytype],
                                        calc_av_lp_real[season][daytype])

            # Calculate R_squared
            slope, intercept, r_value, p_value, std_err = stats.linregress(
                calc_av_lp_modelled[season][daytype],
                calc_av_lp_real[season][daytype])

            # Calculate standard deviation
            std_dev_p = np.std(calc_av_lp_real[season][daytype] -
                               calc_av_lp_modelled[season][daytype])
            std_dev_abs = np.std(
                abs(calc_av_lp_real[season][daytype] -
                    calc_av_lp_modelled[season][daytype]))

            # -----------
            # Labelling
            # -----------
            font_additional_info = plotting_styles.font_info()

            title_info = ('{}, {}'.format(season, daytype))
            plt.text(
                1, 0.55, "RMSE: {}, R_squared: {}, std: {} (+- {})".format(
                    round(rmse, 2),
                    round(r_value, 2),
                    round(std_dev_p, 2),
                    round(std_dev_abs, 2),
                    fontdict=font_additional_info))
            plt.title(title_info, loc='left', fontdict=font_additional_info)

    # ------------
    # Plot legend
    # ------------
    plt.legend(ncol=1,
               loc=2,
               prop={
                   'family': 'arial',
                   'size': 5
               },
               frameon=False)

    # Tight layout
    plt.tight_layout()
    plt.margins(x=0)

    fig.savefig(path_plot_fig)

    if plotshow:
        plt.show()
        plt.close()
    else:
        plt.close()
示例#7
0
def spatial_validation(reg_coord,
                       subnational_modelled,
                       subnational_real,
                       regions,
                       fueltype_str,
                       fig_name,
                       label_points=False,
                       plotshow=False):
    """Compare gas/elec demand for LADs

    Arguments
    ----------
    lad_infos_shapefile : dict
        Infos of shapefile (dbf / csv)
    ed_fueltype_regs_yh : object
        Regional fuel Given as GWh (?)
    subnational_real : dict
        for electricity: Sub-national electrcity demand given as GWh

    Note
    -----
    SOURCE OF LADS:
        - Data for northern ireland is not included in that, however in BEIS dataset!
    """
    logging.debug("... Validation of spatial disaggregation")
    result_dict = {}
    result_dict['real_demand'] = {}
    result_dict['modelled_demand'] = {}

    # -------------------------------------------
    # Match ECUK sub-regional demand with geocode
    # -------------------------------------------
    for region in regions:
        for reg_geocode in reg_coord:
            if reg_geocode == region:

                try:
                    # Test wheter data is provided for LAD or owtherwise ignore
                    if subnational_real[reg_geocode] == 0:
                        pass
                    else:
                        # --Sub Regional Electricity demand (as GWh)
                        result_dict['real_demand'][
                            reg_geocode] = subnational_real[reg_geocode]
                        result_dict['modelled_demand'][
                            reg_geocode] = subnational_modelled[reg_geocode]

                except KeyError:
                    logging.warning(
                        "Sub-national spatial validation: No fuel for region %s",
                        reg_geocode)

    # --------------------
    # Calculate statistics
    # --------------------
    diff_real_modelled_p = []
    diff_real_modelled_abs = []

    for reg_geocode in regions:
        try:
            real = result_dict['real_demand'][reg_geocode]
            modelled = result_dict['modelled_demand'][reg_geocode]

            diff_real_modelled_p.append((100 / real) * modelled)
            diff_real_modelled_abs.append(real - modelled)
        except KeyError:
            pass

    # Calculate the average deviation between reald and modelled
    av_deviation_real_modelled = np.average(diff_real_modelled_p)

    # Calculate standard deviation
    std_dev_p = np.std(diff_real_modelled_p)  # Given as percent
    std_dev_abs = np.std(diff_real_modelled_abs)  # Given as energy unit

    # -----------------
    # Sort results according to size
    # -----------------
    sorted_dict_real = sorted(result_dict['real_demand'].items(),
                              key=operator.itemgetter(1))

    # -------------------------------------
    # Plot
    # -------------------------------------
    fig = plt.figure(figsize=plotting_program.cm2inch(
        9, 8))  #width, height (9, 8)

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

    x_values = np.arange(0, len(sorted_dict_real), 1)

    y_real_demand = []
    y_modelled_demand = []

    labels = []
    for sorted_region in sorted_dict_real:

        geocode_lad = sorted_region[0]

        y_real_demand.append(result_dict['real_demand'][geocode_lad])
        y_modelled_demand.append(result_dict['modelled_demand'][geocode_lad])

        logging.info(
            "validation %s LAD %s: %s %s (%s p diff)", fueltype_str,
            geocode_lad, round(result_dict['real_demand'][geocode_lad], 4),
            round(result_dict['modelled_demand'][geocode_lad], 4),
            round(
                100 - (100 / result_dict['real_demand'][geocode_lad]) *
                result_dict['modelled_demand'][geocode_lad], 4))

        # Labels
        labels.append(geocode_lad)

    # Calculate r_squared
    _slope, _intercept, r_value, _p_value, _std_err = stats.linregress(
        y_real_demand, y_modelled_demand)

    # --------
    # Axis
    # --------
    plt.tick_params(
        axis='x',  # changes apply to the x-axis
        which='both',  # both major and minor ticks are affected
        bottom='off',  # ticks along the bottom edge are off
        top='off',  # ticks along the top edge are off
        labelbottom='off')  # labels along the bottom edge are off

    # ----------------------------------------------
    # Plot
    # ----------------------------------------------
    plt.plot(x_values,
             y_real_demand,
             linestyle='None',
             marker='o',
             markersize=1.6,
             fillstyle='full',
             markerfacecolor='grey',
             markeredgewidth=0.2,
             color='black',
             label='actual')

    plt.plot(x_values,
             y_modelled_demand,
             marker='o',
             linestyle='None',
             markersize=1.6,
             markerfacecolor='white',
             fillstyle='none',
             markeredgewidth=0.5,
             markeredgecolor='blue',
             color='black',
             label='model')

    # Limit
    plt.ylim(ymin=0)

    # -----------
    # Labelling
    # -----------
    if label_points:
        for pos, txt in enumerate(labels):

            ax.text(x_values[pos],
                    y_modelled_demand[pos],
                    txt,
                    horizontalalignment="right",
                    verticalalignment="top",
                    fontsize=3)

    font_additional_info = plotting_styles.font_info()

    font_additional_info['size'] = 6

    title_info = ('R_2: {}, std_%: {} (GWh {}), av_diff_%: {}'.format(
        round(r_value, 2), round(std_dev_p, 2), round(std_dev_abs, 2),
        round(av_deviation_real_modelled, 2)))

    plt.title(title_info, loc='left', fontdict=font_additional_info)

    plt.xlabel("UK regions (excluding northern ireland)")
    plt.ylabel("{} [GWh]".format(fueltype_str))

    # --------
    # Legend
    # --------
    plt.legend(prop={'family': 'arial', 'size': 8}, frameon=False)

    # Tight layout
    plt.margins(x=0)
    plt.tight_layout()
    plt.savefig(fig_name)

    if plotshow:
        plt.show()
    else:
        plt.close()
示例#8
0
def compare_results(name_fig,
                    path_result,
                    y_factored_indo,
                    y_calculated_array,
                    title_left,
                    days_to_plot,
                    plot_crit=False):
    """Compare national electrictiy demand data with model results

    Note
    ----
    RMSE fit criteria : Lower values of RMSE indicate better fit
    https://stackoverflow.com/questions/17197492/root-mean-square-error-in-python

    https://matplotlib.org/examples/lines_bars_and_markers/marker_fillstyle_reference.html
    """
    logging.debug("...compare elec results")
    nr_of_h_to_plot = len(days_to_plot) * 24

    x_data = range(nr_of_h_to_plot)

    y_real_indo_factored = []
    y_calculated_list = []
    y_diff_p = []
    y_diff_abs = []

    for day in days_to_plot:
        for hour in range(24):
            y_calculated_list.append(y_calculated_array[day][hour])
            y_real_indo_factored.append(y_factored_indo[day][hour])

            # Calculate absolute differences
            abs_diff = abs(y_factored_indo[day][hour] -
                           y_calculated_array[day][hour])
            y_diff_abs.append(abs_diff)

            # Calculate difference in percent
            if abs_diff == 0:
                p_diff = 0
            else:
                p_diff = (100 / y_factored_indo[day][hour]
                          ) * y_calculated_array[day][hour] - 100

            y_diff_p.append(p_diff)

    # -------------
    # RMSE
    # -------------
    rmse_val_corrected = basic_functions.rmse(np.array(y_real_indo_factored),
                                              np.array(y_calculated_list))

    # ----------
    # Standard deviation
    # ----------
    standard_dev_real_modelled = np.std(y_diff_p)  # Differences in %
    standard_dev_real_modelled_abs = np.std(y_diff_abs)  # Absolute differences

    logging.info("Standard deviation given as percentage: " +
                 str(standard_dev_real_modelled))
    logging.info("Standard deviation given as GW:         " +
                 str(standard_dev_real_modelled_abs))

    # ---------
    # R squared
    # ---------
    slope, intercept, r_value, p_value, std_err = stats.linregress(
        y_real_indo_factored, y_calculated_list)

    # ----------
    # Plot residuals
    # ----------
    #try:
    #    plot_residual_histogram(
    #        y_diff_p, path_result, "residuals_{}".format(name_fig))
    #except:
    #    pass

    # ----------
    # Plot figure
    # ----------
    fig = plt.figure(figsize=basic_plot_functions.cm2inch(22, 8))

    # smooth line
    x_data_smoothed, y_real_indo_factored_smoothed = basic_plot_functions.smooth_data(
        x_data, y_real_indo_factored, num=40000)

    # plot points
    plt.plot(x_data_smoothed,
             y_real_indo_factored_smoothed,
             label='indo_factored',
             linestyle='-',
             linewidth=0.5,
             fillstyle='full',
             color='black')

    # smooth line
    x_data_smoothed, y_calculated_list_smoothed = basic_plot_functions.smooth_data(
        x_data, y_calculated_list, num=40000)

    plt.plot(x_data_smoothed,
             y_calculated_list_smoothed,
             label='model',
             linestyle='--',
             linewidth=0.5,
             fillstyle='full',
             color='blue')

    plt.xlim([0, 8760])
    plt.margins(x=0)
    plt.axis('tight')

    # --------------------------------------
    # Label x axis in dates
    # --------------------------------------
    major_ticks_days, major_ticks_labels = get_date_strings(days_to_plot,
                                                            daystep=1)

    plt.xticks(major_ticks_days, major_ticks_labels)

    # ----------
    # Labelling
    # ----------
    font_additional_info = plotting_styles.font_info(size=4)

    plt.title('RMSE: {} Std_dev_% {} (+-{} GW) R_2: {}'.format(
        round(rmse_val_corrected, 3), round(standard_dev_real_modelled, 3),
        round(standard_dev_real_modelled_abs, 3), round(r_value, 3)),
              fontdict=font_additional_info,
              loc='right')

    plt.title(title_left, loc='left')

    plt.xlabel("hour", fontsize=10)
    plt.ylabel("uk elec use [GW] for {}".format(title_left), fontsize=10)

    plt.legend(frameon=False)

    plt.savefig(os.path.join(path_result, name_fig))

    if plot_crit:
        plt.show()
    plt.close()
def main(regions, weather_regions, data):
    """Plot weighted HDD (HDD per Region & region pop)
    with national gas demand
    Note
    ----
    Comparison with national demand is not perfect
    because not all electricity use depends on hdd
    """
    base_yr = 2015
    # ----------------------------------
    # Read temp data and weather station
    # ----------------------------------
    weighted_daily_hdd = np.zeros((365))
    #weighted_daily_hdd_pop = np.zeros((365))

    for region in regions:

        # Get closest weather station to `Region`
        closest_weather_station = get_closest_station(
            data['reg_coord'][region]['longitude'],
            data['reg_coord'][region]['latitude'], data['weather_stations'])

        closest_weather_region = weather_regions[closest_weather_station]

        reg_pop = data['scenario_data']['population'][base_yr][region]

        for day in range(365):
            reg_hdd_day = closest_weather_region.rs_hdd_by[day]

            # ----------------------------
            # Weighted HDD with population
            # ----------------------------
            # WEIGHT WITH POP / TWO OPTIONS
            weighted_daily_hdd[day] += reg_hdd_day * reg_pop
            #weighted_daily_hdd_pop[day] += reg_hdd_day * reg_pop

    # -------------------------------
    # Calculate sum of HDD across all regions for every day [reg][day] --> [day]
    # -------------------------------

    # Convert to list
    weighted_daily_hdd = list(weighted_daily_hdd)
    #weighted_daily_hdd_pop = list(weighted_daily_hdd_pop)
    # -- Non daily metered gas demand in mcm == Residential heating gas
    # demand for year 2015 (Jan - Dez --> Across two excel in orig file)
    # gas demand for 365 days

    # Unit: GWh per day
    gas_demand_NDM_2015_2016_gwh = [
        2059.3346672, 2170.0185108, 2098.5700609, 2129.0042078, 2183.3908583,
        2183.3755211, 2181.77478289999, 2180.2661608, 2171.9539465,
        2093.1630535, 2123.4248103, 2177.2511151, 2177.4395409, 2177.4392085,
        2175.2222323, 2166.6139387, 2087.285658, 2115.1954239, 2167.4317226,
        2166.5545797, 2164.694753, 2163.4837384, 2157.386435, 2080.9887003,
        2111.8947958, 2166.0717924, 2162.6456414, 2159.295252, 2155.8334129,
        2145.8472366, 2061.1717803, 2082.3903686, 2127.0822845, 2118.2712922,
        2113.193853, 2107.8898595, 2095.8412092, 2014.9440596, 2049.2258347,
        2107.0791469, 2112.1583269, 2117.2396604, 2123.0313351, 2122.1358234,
        2051.7066905, 2087.3670451, 2136.4535688, 2132.1460485, 2128.3906968,
        2124.2843977, 2105.6629196, 2019.1113801, 2036.5569675, 2077.2039557,
        2061.8101344, 2046.7869234, 2031.4318873, 2005.2602169, 1914.0892568,
        1922.9069295, 1954.9594171, 1933.6480271, 1912.3061523, 1890.5476499,
        1862.3706414, 1775.6671805, 1783.4502818, 1814.9200643, 1796.8545889,
        1784.4710306, 1771.6500082, 1752.3369114, 1674.0247522, 1687.99816,
        1726.2909774, 1715.8915875, 1705.7032311, 1692.0716697, 1671.1552101,
        1594.1241588, 1603.713891, 1636.247885, 1620.6947572, 1605.2659081,
        1590.0104955, 1569.4656755, 1494.5719877, 1502.5278704, 1535.2362037,
        1526.2747126, 1513.4608687, 1504.8484041, 1490.7666095, 1325.9250159,
        1316.9165572, 1462.4932465, 1458.1802196, 1442.6262542, 1426.8417784,
        1411.3589019, 1335.8538668, 1333.6755582, 1356.6697705, 1334.994619,
        1313.3468669, 1291.2764263, 1261.7044342, 1187.3254679, 1182.7090036,
        1206.201116, 1187.9607269, 1169.0975458, 1150.8622665, 1125.7570188,
        1059.6150794, 1057.5077396, 1081.4643041, 1065.2552632, 1049.0529795,
        1032.9539024, 1007.1793016, 914.58361712, 897.87864486, 880.61178046,
        909.11557166, 890.86945346, 871.96514751, 853.8612021, 791.8538562,
        775.11686001, 832.03363633, 814.21901615, 799.58233329, 784.71165334,
        761.63725303, 707.19260431, 704.66692408, 729.32567359, 716.8394616,
        704.16329367, 692.60720982, 673.62744381, 625.16539826, 616.31467523,
        606.17192685, 636.72436643, 625.93400599, 615.10886486, 605.22026297,
        557.46992056, 551.34168138, 578.47909485, 570.13253752, 561.78823047,
        553.3654021, 538.91778989, 498.94506464, 500.61103512, 529.17638846,
        522.76561207, 516.42800386, 510.56638091, 496.03207692, 456.62523814,
        456.93248186, 484.57825041, 478.35283027, 472.67018165, 467.07413108,
        452.94073995, 415.61047941, 417.54936646, 447.87992936, 444.32552312,
        440.34388174, 436.93497309, 425.39778941, 390.98147195, 393.27803263,
        422.2499116, 418.01587597, 413.61939995, 409.40057065, 397.24314025,
        362.84744615, 363.93696426, 393.56430501, 390.46598983, 387.50245828,
        384.08572436, 373.79849944, 341.87745791, 344.96303388, 375.65480602,
        374.49215286, 372.75648874, 371.74226978, 361.8690835, 331.52439876,
        335.15290392, 366.77742567, 365.12052235, 364.02193295, 362.52261752,
        352.52451205, 322.45011946, 326.07034766, 357.85885375, 357.46873061,
        356.17585959, 356.18529447, 347.76795445, 318.87093053, 323.44991194,
        357.14307241, 358.48343406, 359.41495, 360.13619174, 352.30573134,
        323.75524954, 328.47959503, 361.26301948, 361.91381511, 362.52822042,
        363.04084256, 354.83105903, 327.4003489, 333.7913569, 367.75844026,
        369.11519087, 372.6949059, 375.8462941, 371.01068634, 344.6986732,
        353.4825506, 390.13714534, 393.84951909, 397.83499025, 401.57927692,
        396.97028525, 370.21486247, 379.29129941, 416.16743945, 420.07485221,
        423.97519461, 429.74321627, 427.2986801, 401.46194542, 413.22870233,
        456.07775396, 465.3295712, 474.21723331, 483.12391875, 484.18266475,
        461.009664, 476.92695202, 521.59453157, 530.84505032, 540.18546168,
        549.72258375, 551.25306059, 525.45532919, 542.29079386, 587.07994975,
        596.34233521, 607.50869098, 618.97893781, 622.86393906, 597.19837803,
        621.39030489, 674.41691171, 690.65537739, 706.66602486, 750.44401705,
        761.5020047, 735.3577927, 758.94313283, 820.97761046, 841.64549132,
        862.82785312, 882.73942176, 895.8174329, 867.22285798, 895.86950089,
        962.4264397, 986.21496809, 1010.5025124, 1034.947993, 1049.36376,
        1016.2553526, 1045.7292098, 1113.1746337, 1125.8164178, 1141.3139762,
        1159.7889682, 1167.2284687, 1125.5987857, 1158.1749163, 1228.6271493,
        1250.8619219, 1276.6254017, 1300.3160004, 1317.8170358, 1282.8879339,
        1320.3942354, 1394.2587548, 1416.5190559, 1438.5435458, 1461.7634807,
        1479.7562971, 1438.8539543, 1478.9216764, 1557.1207719, 1573.4090718,
        1587.6655331, 1603.6341589, 1613.333634, 1562.3586478, 1600.277806,
        1679.9344601, 1697.4619665, 1712.8552817, 1724.7516139, 1724.0138982,
        1657.0594241, 1682.3440925, 1748.5809406, 1752.9203251, 1763.9782637,
        1775.1642524, 1782.4227695, 1722.1387718, 1761.2175743, 1843.516748,
        1861.6814774, 1873.721509, 1884.7695907, 1889.1761128, 1820.2893554,
        1849.3759024, 1927.6865797, 1941.1637845, 1949.9179591, 1955.9424808,
        1956.9521671, 1880.0208367, 1906.0644726, 1980.6623416, 1988.0433795,
        1992.2170495, 2003.9919664, 2009.5777063, 1937.9896745, 1964.8414739,
        2036.894857, 2044.9981179, 2053.3450878, 1974.8040044, 1814.6135915,
        1904.8874509, 1909.229843, 1911.2513971, 1995.545462, 1995.3479943,
        1997.4328038
    ]

    # Total SND (includes IUK exports and storage injection)
    gas_demand_TOTALSND_2015_2016 = [
        3017, 3218, 3093, 3105, 3281, 3281, 3280, 3279, 3246, 3089, 3101, 3277,
        3278, 3278, 3276, 3242, 3085, 3095, 3270, 3269, 3267, 3267, 3235, 3081,
        3093, 3270, 3267, 3264, 3261, 3226, 3063, 3066, 3234, 3226, 3221, 3216,
        3179, 3020, 3035, 3217, 3222, 3227, 3233, 3207, 3056, 3073, 3246, 3241,
        3237, 3233, 3188, 3023, 3022, 3185, 3170, 3155, 3139, 3088, 2919, 2904,
        3058, 3037, 3016, 2994, 2941, 2773, 2764, 2915, 2897, 2885, 2872, 2828,
        2673, 2669, 2826, 2816, 2805, 2792, 2746, 2594, 2586, 2736, 2720, 2705,
        2690, 2645, 2496, 2486, 2635, 2626, 2597, 2588, 2537, 2311, 2300, 2527,
        2541, 2526, 2510, 2476, 2340, 2321, 2458, 2436, 2413, 2391, 2339, 2193,
        2175, 2315, 2302, 2287, 2274, 2230, 2098, 2084, 2223, 2211, 2200, 2190,
        2142, 1975, 1961, 2009, 2064, 2050, 2036, 2006, 1885, 1871, 2035, 2022,
        2012, 2002, 1967, 1848, 1834, 1969, 1961, 1952, 1945, 1908, 1795, 1778,
        1848, 1888, 1881, 1874, 1850, 1746, 1738, 1872, 1867, 1862, 1857, 1825,
        1721, 1711, 1845, 1842, 1839, 1836, 1803, 1700, 1689, 1821, 1817, 1814,
        1811, 1778, 1677, 1667, 1801, 1799, 1797, 1796, 1766, 1667, 1657, 1788,
        1786, 1708, 1705, 1674, 1584, 1573, 1693, 1691, 1690, 1688, 1659, 1571,
        1562, 1682, 1681, 1679, 1678, 1650, 1563, 1553, 1673, 1672, 1670, 1669,
        1637, 1550, 1540, 1660, 1659, 1657, 1656, 1628, 1542, 1533, 1653, 1653,
        1652, 1654, 1626, 1541, 1531, 1649, 1648, 1647, 1646, 1619, 1534, 1526,
        1646, 1646, 1648, 1650, 1625, 1540, 1534, 1657, 1659, 1661, 1663, 1638,
        1551, 1545, 1669, 1670, 1672, 1675, 1651, 1564, 1560, 1691, 1697, 1703,
        1709, 1688, 1602, 1601, 1735, 1742, 1748, 1754, 1733, 1643, 1643, 1779,
        1784, 1792, 1803, 1783, 1692, 1698, 1843, 1855, 1867, 2041, 2009, 1868,
        1873, 2089, 2103, 2119, 2132, 2102, 1958, 1968, 2188, 2206, 2224, 2242,
        2212, 2063, 2074, 2296, 2303, 2312, 2324, 2288, 2130, 2143, 2369, 2385,
        2404, 2422, 2395, 2243, 2261, 2491, 2508, 2524, 2541, 2514, 2357, 2376,
        2612, 2623, 2633, 2649, 2619, 2457, 2481, 2725, 2743, 2758, 2771, 2731,
        2552, 2563, 2796, 2801, 2812, 2824, 2791, 2618, 2642, 2893, 2911, 2923,
        2935, 2899, 2716, 2730, 2979, 2993, 3002, 3008, 2969, 2777, 2788, 3035,
        3042, 3047, 3059, 3024, 2835, 2847, 3033, 3041, 3050, 2907, 2758, 2710,
        2715, 2816, 2929, 2930, 2932
    ]

    # ----------------
    # Linear regression
    # ----------------
    def lin_func(x, slope, intercept):
        y = slope * x + intercept
        return y

    slope, intercept, r_value, p_value, std_err = stats.linregress(
        gas_demand_NDM_2015_2016_gwh, weighted_daily_hdd)

    logging.warning("Slope:         %s", str(slope))
    logging.warning("intercept:     %s", str(intercept))
    logging.warning("r_value:       %s", str(r_value))
    logging.warning("p_value:       %s", str(p_value))
    logging.warning("std_err:       %s", str(std_err))
    logging.warning("sum:           %s", str(sum(weighted_daily_hdd)))
    logging.warning("av:            %s",
                    str(sum(weighted_daily_hdd) / len(weighted_daily_hdd)))
    logging.warning("Nr of reg:     %s", str(len(regions)))
    logging.warning("nr of days (gray points): " +
                    str(len(gas_demand_NDM_2015_2016_gwh)))
    logging.warning("Nr of days:    " + str(len(weighted_daily_hdd)))

    # Set figure size in cm
    plt.figure(figsize=plotting_program.cm2inch(8, 8))

    # ----------------
    # PLoty daily GWh (Points are days)
    # ----------------
    plt.plot(gas_demand_NDM_2015_2016_gwh,
             weighted_daily_hdd,
             linestyle='None',
             marker='o',
             markersize=2.7,
             fillstyle='full',
             markerfacecolor='grey',
             markeredgewidth=0.2,
             color='grey')

    # ---------------------
    # Plot regression line
    # ---------------------
    x_plot = np.linspace(270, 2200, 500)
    y_plot = []
    for x in x_plot:
        y_plot.append(lin_func(x, slope, intercept))
    plt.plot(x_plot, y_plot, color='black', linestyle='--')

    plt.xlim(0, 2300)

    # ---------------------
    # Labelling
    # ---------------------
    font_additional_info = plotting_styles.font_info()
    #plt.xlabel("UK non daily metered gas demand [GWh per day]")
    #plt.ylabel("HDD * POP [mio]")
    plt.title("slope: {}, intercept: {}, r2: {})".format(
        round(slope, 3), round(intercept, 3), round(r_value, 3)),
              fontdict=font_additional_info)

    plt.tight_layout()
    plt.margins(x=0)
    plt.show()
示例#10
0
def plot_cross_graphs_scenarios(base_yr, comparison_year, regions,
                                scenario_data, fueltype_int, fueltype_str,
                                fig_name, label_points, plotshow):

    result_dict = defaultdict(dict)

    # -------------------------------------------
    # Get base year modelled demand of any scenario (becasue base year the same in every scenario)
    # -------------------------------------------$
    all_scenarios = list(scenario_data.keys())
    first_scenario = all_scenarios[0]
    ed_year_fueltype_regs_yh = scenario_data[first_scenario][
        'ed_fueltype_regs_yh']

    for year, fuels in ed_year_fueltype_regs_yh.items():

        if year == base_yr:
            for reg_nr, reg_geocode in enumerate(regions):
                result_dict['demand_by'][reg_geocode] = np.sum(
                    fuels[fueltype_int][reg_nr])
                result_dict['peak_h_demand_by'][reg_geocode] = np.max(
                    fuels[fueltype_int][reg_nr])

            # Demand across all regs
            result_dict['demand_by_all_regs'] = np.sum(fuels[fueltype_int])

            # Peak demand
            fuel_all_reg_yh = np.sum(fuels[fueltype_int],
                                     axis=0)  # Sum across all regions
            result_dict['peak_h_demand_by_all_regs'] = np.max(fuel_all_reg_yh)

            # Calculate national load factor
            fuel_all_fueltype_reg_yh = np.sum(
                fuels, axis=1)  # Sum across all regions per fueltype
            load_factor_y = load_factors.calc_lf_y(fuel_all_fueltype_reg_yh)
            result_dict['lf_by_all_regs_av'] = load_factor_y[fueltype_int]

    for scenario, data in scenario_data.items():
        result_dict['demand_cy'][scenario] = {}
        result_dict['peak_h_demand_cy'][scenario] = {}

        for year, fuels in data['ed_fueltype_regs_yh'].items():
            if year == comparison_year:
                for reg_nr, reg_geocode in enumerate(regions):
                    result_dict['demand_cy'][scenario][reg_geocode] = np.sum(
                        fuels[fueltype_int][reg_nr])
                    result_dict['peak_h_demand_cy'][scenario][
                        reg_geocode] = np.max(fuels[fueltype_int][reg_nr])

                # Demand across all regs
                result_dict['demand_cy_all_regs'][scenario] = np.sum(
                    fuels[fueltype_int])

                # Peak demand
                fuel_all_reg_yh = np.sum(fuels[fueltype_int],
                                         axis=0)  # Sum across all regions
                result_dict['peak_h_demand_cy_all_regs'][scenario] = np.max(
                    fuel_all_reg_yh)

                # Calculate national load factor
                fuel_all_fueltype_reg_yh = np.sum(
                    fuels, axis=1)  # Sum across all regions per fueltype
                load_factor_y = load_factors.calc_lf_y(
                    fuel_all_fueltype_reg_yh)
                result_dict['lf_cy_all_regs_av'][scenario] = load_factor_y[
                    fueltype_int]
            else:
                pass

    # Get load factor of base year
    reg_load_factor_y = scenario_data[first_scenario]['reg_load_factor_y']
    for year, lf_fueltype_regs in reg_load_factor_y.items():
        if year == base_yr:
            for reg_nr, reg_geocode in enumerate(regions):
                result_dict['lf_by'][reg_geocode] = lf_fueltype_regs[
                    fueltype_int][reg_nr]

    for scenario, data in scenario_data.items():
        reg_load_factor_y = scenario_data[scenario]['reg_load_factor_y']
        result_dict['lf_cy'][scenario] = {}

        for year, lf_fueltype_regs in reg_load_factor_y.items():
            if year == comparison_year:
                for reg_nr, reg_geocode in enumerate(regions):
                    result_dict['lf_cy'][scenario][
                        reg_geocode] = lf_fueltype_regs[fueltype_int][reg_nr]
            else:
                pass

    # --------------------------
    # Iterate scenario and plot
    # --------------------------
    fig = plt.figure(figsize=basic_plot_functions.cm2inch(18,
                                                          8))  #width, height

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

    color_list = plotting_styles.color_list_scenarios()

    marker_list = plotting_styles.marker_list()

    all_x_values = []
    all_y_values = []

    for scenario_nr, scenario in enumerate(all_scenarios):
        labels = []
        x_values, y_values = [], []

        for reg_nr, reg_geocode in enumerate(regions):

            # Change in load factor
            lf_change_p = ((100 / result_dict['lf_by'][reg_geocode]) *
                           result_dict['lf_cy'][scenario][reg_geocode]) - 100

            # Change in peak h deman
            demand_peak_h_p = (
                (100 / result_dict['peak_h_demand_by'][reg_geocode]) *
                result_dict['peak_h_demand_cy'][scenario][reg_geocode]) - 100

            # Change in total regional demand
            tot_demand_p = (
                (100 / result_dict['demand_by'][reg_geocode]) *
                result_dict['demand_cy'][scenario][reg_geocode]) - 100

            x_values.append(lf_change_p)
            #y_values.append(tot_demand_p)
            y_values.append(demand_peak_h_p)

            #print("ADDING {} {} {}".format(reg_nr, round(lf_change_p, 3), round(demand_peak_h_p, 3)))

            labels.append(reg_geocode)

        # Add average
        national_tot_cy_p = ((100 / result_dict['lf_by_all_regs_av']) *
                             result_dict['lf_cy_all_regs_av'][scenario]) - 100
        #national_tot_demand_p = ((100 / result_dict['demand_by_all_regs']) * result_dict['demand_cy_all_regs'][scenario]) - 100
        national_peak_h_p = (
            (100 / result_dict['peak_h_demand_by_all_regs']) *
            result_dict['peak_h_demand_cy_all_regs'][scenario]) - 100

        x_val_national_lf_demand_cy = [national_tot_cy_p]
        #y_val_national_lf_demand_cy = [national_tot_demand_p]
        y_val_national_lf_demand_cy = [national_peak_h_p]

        all_x_values += x_values
        all_y_values += y_values
        # -------------------------------------
        # Plot
        # -------------------------------------
        color = color_list[scenario_nr]
        marker = marker_list[scenario_nr]

        alpha_value = 0.6
        marker_size = 7
        ax.scatter(
            x_values,
            y_values,
            alpha=alpha_value,
            color=color,
            #marker=marker,
            edgecolor=color,
            linewidth=0.5,
            s=marker_size,
            label=scenario)

        # Add average
        ax.scatter(x_val_national_lf_demand_cy,
                   y_val_national_lf_demand_cy,
                   alpha=1.0,
                   color=color,
                   s=20,
                   marker="v",
                   linewidth=0.5,
                   edgecolor='black',
                   label='national')

    # --------
    # Axis
    # --------
    ax.set_xlabel("load factor change (%) {}".format(fueltype_str))
    ax.set_ylabel("change in peak h (%) {}".format(fueltype_str))

    plt.tick_params(
        axis='x',  # changes apply to the x-axis
        which='both',  # both major and minor ticks are affected
        bottom='on',  # ticks along the bottom edge are off
        top='off',  # ticks along the top edge are off
        labelbottom='on')  # labels along the bottom edge are off

    # --------
    # Grd
    # --------
    ax.set_axisbelow(True)
    #ax.grid(True)
    #ax.set_xticks(minor=False)
    ax.set_xticks([0], minor=True)
    #ax.set_yticks(minor=False)
    ax.set_yticks([0], minor=True)
    #ax.yaxis.grid(True, which='major')
    ax.yaxis.grid(True,
                  which='minor',
                  linewidth=0.7,
                  color='grey',
                  linestyle='--')
    #ax.xaxis.grid(True, which='major')
    ax.xaxis.grid(True,
                  which='minor',
                  linewidth=0.7,
                  color='grey',
                  linestyle='--')

    # Limit
    #plt.ylim(ymin=0)

    # -----------
    # Labelling
    # -----------
    if label_points:
        for pos, txt in enumerate(labels):
            ax.text(x_values[pos],
                    y_values[pos],
                    txt,
                    horizontalalignment="right",
                    verticalalignment="top",
                    fontsize=6)

    # -------
    # Title information
    # -------
    max_lf = round(max(all_x_values), 2)
    min_lf = round(min(all_x_values), 2)
    min_peak_h = round(min(all_y_values), 2)
    max_peak_h = round(max(all_y_values), 2)

    font_additional_info = plotting_styles.font_info(size=4)

    plt.title("max_peak_h: {} min_peak_h: {}, min_lf: {} max_lf: {}".format(
        max_peak_h, min_peak_h, min_lf, max_lf),
              fontdict=font_additional_info)

    # --------
    # Legend
    # --------
    plt.legend(loc='best',
               ncol=1,
               prop={
                   'family': 'arial',
                   'size': 3
               },
               frameon=False)

    # Tight layout
    plt.margins(x=0)
    plt.tight_layout()
    plt.savefig(fig_name)

    if plotshow:
        plt.show()
    plt.close()
示例#11
0
def compare_peak(
        name_fig,
        path_result,
        validation_elec_2015_peak,
        modelled_peak_dh
    ):
    """Compare peak electricity day with calculated peak energy demand

    Arguments
    ---------
    name_fig : str
        Name of figure
    local_paths : dict
        Paths
    validation_elec_2015_peak : array
        Real data of peak day
    modelled_peak_dh : array
        Modelled peak day
    """
    logging.debug("...compare elec peak results")

    # -------------------------------
    # Compare values
    # -------------------------------
    fig = plt.figure(figsize=plotting_program.cm2inch(8, 8))

    plt.plot(
        range(24),
        modelled_peak_dh,
        color='blue',
        linestyle='-',
        linewidth=0.5,
        label='model')
    #plt.plot(range(24), validation_elec_data_2015[max_day], color='green', label='real')
    plt.plot(
        range(24),
        validation_elec_2015_peak,
        color='black',
        linestyle='--',
        linewidth=0.5,
        label='actual')

    # Calculate hourly differences in %
    diff_p_h = np.round((100 / validation_elec_2015_peak) * modelled_peak_dh, 1)

    # Y-axis ticks
    plt.xlim(0, 25)
    plt.yticks(range(0, 90, 10))

    # Legend
    plt.legend(frameon=False)

    font_additional_info = plotting_styles.font_info()

    # Labelling
    plt.title("peak comparison") # d_%:{}".format(diff_p_h), loc='left', fontdict=font_additional_info)
    plt.xlabel("h")
    plt.ylabel("uk electrictiy use [GW]")

    plt.text(
        -6, 0, diff_p_h, 
        horizontalalignment='center',
        fontdict={
        'family': 'arial',
        'color': 'black',
        'weight': 'normal',
        'size': 6})

    # Tight layout
    plt.tight_layout()
    plt.margins(x=0)

    # Save fig
    plt.savefig(os.path.join(path_result, name_fig))
    plt.close()
def plot_spatial_validation(simulation_yr_to_plot,
                            non_regional_modelled,
                            regional_modelled,
                            subnational_real,
                            regions,
                            fueltype_str,
                            fig_path,
                            label_points=False,
                            plotshow=False):
    result_dict = {}
    result_dict['real_demand'] = {}
    result_dict['modelled_demand'] = {}
    result_dict['modelled_demands_regional'] = {}

    fueltype_int = tech_related.get_fueltype_int(fueltype_str)

    # -------------------------------------------
    # Match ECUK sub-regional demand with geocode
    # -------------------------------------------
    for region_nr, region in enumerate(regions):
        try:
            # --Sub Regional Electricity demand (as GWh)
            real = subnational_real[region]
            modelled = non_regional_modelled[region]
            result_dict['real_demand'][region] = real
            result_dict['modelled_demand'][region] = modelled

        except KeyError:
            logging.debug(
                "Sub-national spatial validation: No fuel for region %s",
                region)

        # Do this for every weather station data
        for weather_station in regional_modelled:
            try:
                _reg_demand = regional_modelled[weather_station][
                    simulation_yr_to_plot][fueltype_int][region_nr]
                result_dict['modelled_demands_regional'][region].append(
                    _reg_demand)
            except KeyError:
                _reg_demand = regional_modelled[weather_station][
                    simulation_yr_to_plot][fueltype_int][region_nr]
                result_dict['modelled_demands_regional'][region] = [
                    _reg_demand
                ]

    # --------------------
    # Calculate statistics
    # --------------------
    diff_real_modelled_p = []
    diff_real_modelled_abs = []

    for region in regions:
        try:
            real = result_dict['real_demand'][region]
            modelled = result_dict['modelled_demand'][region]
            diff_real_modelled_p.append(abs(100 - ((100 / real) * modelled)))
            diff_real_modelled_abs.append(real - modelled)
        except KeyError:
            pass

    # Calculate the average deviation between reald and modelled
    av_deviation_real_modelled = np.average(diff_real_modelled_p)
    median_absolute_deviation = np.median(
        diff_real_modelled_p)  # median deviation

    # Calculate standard deviation
    std_dev_p = np.std(diff_real_modelled_p)  # Given as percent
    std_dev_abs = np.std(diff_real_modelled_abs)  # Given as energy unit

    # -----------------
    # Sort results according to size
    # -----------------
    sorted_dict_real = sorted(result_dict['real_demand'].items(),
                              key=operator.itemgetter(1))

    # -------------------------------------
    # Plot
    # -------------------------------------
    fig = plt.figure(figsize=basic_plot_functions.cm2inch(9, 8))
    ax = fig.add_subplot(1, 1, 1)
    x_values = np.arange(0, len(sorted_dict_real), 1)
    y_real_demand = []
    y_modelled_demand = []
    y_modelled_demands_non_regional = []
    labels = []

    for sorted_region in sorted_dict_real:
        geocode_lad = sorted_region[0]
        y_real_demand.append(result_dict['real_demand'][geocode_lad])
        y_modelled_demand.append(result_dict['modelled_demand'][geocode_lad])
        y_modelled_demands_non_regional.append(
            result_dict['modelled_demands_regional'][geocode_lad])

        print(
            "validation %s LAD %s: real: %s modelled: %s  modelled percentage: %s (%sp diff)",
            fueltype_str, geocode_lad,
            round(result_dict['real_demand'][geocode_lad], 4),
            round(result_dict['modelled_demand'][geocode_lad], 4),
            round(
                100 / result_dict['real_demand'][geocode_lad] *
                result_dict['modelled_demand'][geocode_lad], 4),
            round(
                100 - (100 / result_dict['real_demand'][geocode_lad] *
                       result_dict['modelled_demand'][geocode_lad]), 4))

        labels.append(geocode_lad)

    # Calculate r_squared
    _slope, _intercept, r_value, _p_value, _std_err = stats.linregress(
        y_real_demand, y_modelled_demand)

    # --------
    # Axis
    # --------
    plt.tick_params(
        axis='x',  # changes apply to the x-axis
        which='both',  # both major and minor ticks are affected
        bottom='off',  # ticks along the bottom edge are off
        top='off',  # ticks along the top edge are off
        labelbottom='off')  # labels along the bottom edge are off

    # ----------------------------------------------
    # Plot
    # ----------------------------------------------
    markersize = 3
    markeredgewidth = 0
    linewidth = 2
    color_real = 'black'
    color_all_stations = 'green'
    color_single_station = 'red'
    plt.plot(x_values,
             y_real_demand,
             linestyle='-',
             marker='o',
             alpha=0.6,
             markersize=markersize,
             fillstyle='full',
             markerfacecolor='black',
             markeredgewidth=markeredgewidth,
             color=color_real,
             label='actual demand')

    plt.plot(x_values,
             y_modelled_demand,
             marker='o',
             linestyle='-',
             markersize=markersize,
             alpha=0.6,
             markerfacecolor='blue',
             fillstyle='none',
             markeredgewidth=markeredgewidth,
             markeredgecolor='blue',
             color=color_all_stations,
             label='modelled using all stations')

    # Demands calculated only from one weather station
    station_nr = 0
    nr_of_stations = len(y_modelled_demands_non_regional[0])
    station_vals = []
    for region_vals in y_modelled_demands_non_regional:
        station_vals.append(region_vals[station_nr])

    plt.plot(x_values,
             station_vals,
             marker='o',
             linestyle='-',
             linewidth=linewidth,
             markersize=markersize,
             alpha=0.6,
             markerfacecolor='green',
             fillstyle='none',
             markeredgewidth=markeredgewidth,
             markeredgecolor='green',
             color=color_single_station,
             label='modelled using only a single stations')
    '''for i in range(nr_of_stations):
        station_data = []
        for reg_nr in range(nr_of_regions):
            station_data.append(y_modelled_demands_non_regional[reg_nr][i])

        plt.plot(
            x_values,
            station_data, #y_modelled_demands_non_regional,
            marker='o',
            linestyle='None',
            markersize=1.6,
            alpha=0.6,
            markerfacecolor='white',
            fillstyle='none',
            markeredgewidth=0.5,
            markeredgecolor='orange',
            color='black',
            label='model')'''
    '''# ------------
    # Collect all values per weather_yr
    list_with_station_vals = []
    for station_i in range(nr_of_stations):
        station_vals = []
        for region_vals in y_modelled_demands_non_regional:
            station_vals.append(region_vals[station_i])
        list_with_station_vals.append(station_vals)

    df = pd.DataFrame(
        list_with_station_vals,
        columns=range(nr_of_regions)) #note not region_rn as ordered

    period_h = range(nr_of_regions)

    quantile_95 = 0.95
    quantile_05 = 0.05

    df_q_95 = df.quantile(quantile_95)
    df_q_05 = df.quantile(quantile_05)

    #Transpose for plotting purposes
    df = df.T
    df_q_95 = df_q_95.T
    df_q_05 = df_q_05.T

    # ---------------
    # Smoothing lines
    # ---------------
    try:
        period_h_smoothed, df_q_95_smoothed = basic_plot_functions.smooth_data(period_h, df_q_95, num=40000)
        period_h_smoothed, df_q_05_smoothed = basic_plot_functions.smooth_data(period_h, df_q_05, num=40000)
    except:
        period_h_smoothed = period_h
        df_q_95_smoothed = df_q_95
        df_q_05_smoothed = df_q_05
    #plt.plot(period_h_smoothed, df_q_05_smoothed, color='black', linestyle='--', linewidth=0.5, label="0.05")
    #plt.plot(period_h_smoothed, df_q_95_smoothed, color='black', linestyle='--', linewidth=0.5, label="0.95")

    # -----------------
    # Uncertainty range
    # -----------------
    plt.fill_between(
        period_h_smoothed, #x
        df_q_95_smoothed,  #y1
        df_q_05_smoothed,  #y2
        alpha=.40,
        facecolor="grey",
        label="uncertainty band")
    # -----------'''

    # Limit
    plt.ylim(ymin=0)

    # -----------
    # Labelling
    # -----------
    if label_points:
        for pos, txt in enumerate(labels):

            ax.text(x_values[pos],
                    y_modelled_demand[pos],
                    txt,
                    horizontalalignment="right",
                    verticalalignment="top",
                    fontsize=1)

    font_additional_info = plotting_styles.font_info(size=4)

    title_info = (
        'R_2: {}, std_%: {} (GWh {}), av_diff_%: {} median_abs_dev: {}'.format(
            round(r_value, 2), round(std_dev_p, 2), round(std_dev_abs, 2),
            round(av_deviation_real_modelled, 2),
            round(median_absolute_deviation, 2)))

    plt.title(title_info, loc='left', fontdict=font_additional_info)

    plt.xlabel("UK regions (excluding northern ireland)")
    plt.ylabel("{} [GWh]".format(fueltype_str))

    # --------
    # Legend
    # --------
    plt.legend(prop={'family': 'arial', 'size': 8}, frameon=False)

    # Tight layout
    plt.margins(x=0)
    plt.tight_layout()
    plt.savefig(fig_path)

    if plotshow:
        plt.show()
    else:
        plt.close()