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()
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()
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()
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()
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()