Source code for UrbanHeatPro.Functions.plot

"""
plot.py
A. Molar-Cruz @ TUM ENS
"""

import matplotlib

matplotlib.use('Agg')

import numpy as np
import os

import matplotlib.pyplot as plt
from matplotlib.dates import MonthLocator, DayLocator, HourLocator, DateFormatter
from matplotlib import cm
from scipy.cluster.hierarchy import dendrogram


# --------------------------------------------------------------------------------
[docs] def plot_timeseries(dt_vector, timeseries, legend, fig_name, xticks=('month', 3), ynumticks='auto', ylabel='Power [kW]', ylim0=True, yfactor=1e3): """ Plots timeseries as steps Args: dt_vector (list): list of datetime objects timeseries (list): timeseries to plot [ts1, ts2, ts3] legend (list): list of legends [leg1, leg2, leg3] fig_name (string): figure name xticks (tuple): Every X months/days/hours. Possible values: ('month', X), ('day', X), ('hour', X) ynumticks ylabel ylim0 yfactor """ # define plot style style_dir = '{}/input/Styles/'.format(os.getcwd()) TUM = style_dir + 'TUM.mplstyle' presentation = style_dir + 'presentation.mplstyle' plt.style.use([TUM, presentation]) # define figure and axes fig, ax = plt.subplots() # plot for iii, ts in enumerate(timeseries): ax.plot(dt_vector, ts / yfactor, label=legend[iii]) ax.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=1, borderaxespad=0., ncol=len(legend)) # x-axis if xticks[0] == 'month': major_ticks = MonthLocator(range(1, 13), bymonthday=1, interval=xticks[1]) minor_ticks = MonthLocator(range(1, 13), bymonthday=1, interval=1) ticksFmt = DateFormatter("%b '%y") elif xticks[0] == 'day': major_ticks = DayLocator(range(1, 32), interval=xticks[1]) minor_ticks = DayLocator(range(1, 32), interval=1) ticksFmt = DateFormatter("%d.%m") elif xticks[0] == 'hour': major_ticks = HourLocator(range(24), interval=xticks[1]) minor_ticks = HourLocator(range(24), interval=1) ticksFmt = DateFormatter("%H") ax.xaxis.set_major_locator(major_ticks) ax.xaxis.set_minor_locator(minor_ticks) ax.xaxis.set_major_formatter(ticksFmt) ax.autoscale_view() # y-axis if ylim0: start, end = ax.get_ylim() ax.set_ylim([0, end]) if ynumticks != 'auto': start, end = ax.get_ylim() step = int(round((end - start) / ynumticks, -1)) ax.yaxis.set_ticks(np.arange(start, step * ynumticks, step)) ax.set_ylabel(ylabel) # save figure fig.savefig(fig_name, dpi=300) # close figure plt.close(fig) # back to classic plot style plt.style.use('classic')
#
[docs] def plot_stacked_timeseries(dt_vector, timeseries, legend, fig_name, xticks=('month', 3), ynumticks='auto', ylabel='Power [kW]', ylim0=True, yfactor=1e3): """ Plots timeseries as steps Args: dt_vector (list): list of datetime objects timeseries (list): timeseries to stack [ts1, ts2] legend (list): list of legends [leg1, leg2, leg3] fig_name (string): figure name xticks (tuple): Every X months/days/hours. Possible values: ('month', X), ('day', X), ('hour', X) ynumticks ylabel ylim0 yfactor """ # define plot style style_dir = '{}/input/Styles/'.format(os.getcwd()) TUM = style_dir + 'TUM.mplstyle' presentation = style_dir + 'presentation.mplstyle' plt.style.use([TUM, presentation]) # define figure and axes fig, ax = plt.subplots() # plot ax.stackplot(dt_vector, timeseries) ax.legend(legend, bbox_to_anchor=(0., 1.02, 1., .102), loc=1, borderaxespad=0., ncol=len(legend)) # x-axis if xticks[0] == 'month': major_ticks = MonthLocator(range(1, 13), bymonthday=1, interval=xticks[1]) minor_ticks = MonthLocator(range(1, 13), bymonthday=1, interval=1) ticksFmt = DateFormatter("%b '%y") elif xticks[0] == 'day': major_ticks = DayLocator(range(1, 32), interval=xticks[1]) minor_ticks = DayLocator(range(1, 32), interval=1) ticksFmt = DateFormatter("%d.%m") elif xticks[0] == 'hour': major_ticks = HourLocator(range(24), interval=xticks[1]) minor_ticks = HourLocator(range(24), interval=1) ticksFmt = DateFormatter("%H") ax.xaxis.set_major_locator(major_ticks) ax.xaxis.set_minor_locator(minor_ticks) ax.xaxis.set_major_formatter(ticksFmt) ax.autoscale_view() # y-axis if ylim0: start, end = ax.get_ylim() ax.set_ylim([0, end]) if ynumticks != 'auto': start, end = ax.get_ylim() step = int(round((end - start) / ynumticks, -1)) ax.yaxis.set_ticks(np.arange(start, step * ynumticks, step)) ax.set_ylabel(ylabel) # save figure fig.savefig(fig_name, dpi=300) # close figure plt.close(fig) # back to classic plot style plt.style.use('classic')
#
[docs] def plot_histogram(values, ylabel, fig_name, factor=1e3, statistics=[]): """ Plots simple histogram """ # define plot style style_dir = '{}/input/Styles/'.format(os.getcwd()) TUM = style_dir + 'TUM.mplstyle' presentation = style_dir + 'presentation.mplstyle' plt.style.use([TUM, presentation]) # define figure and axes fig, ax = plt.subplots(figsize=(10, 5)) # plot hist ax.hist(values / factor, color=(0.8, 0.8, 0.8)) ax.set_ylabel(ylabel) # mean mean = (values / factor).mean() ax.axvline(mean, linestyle='dashed', linewidth=2) # save figure fig.savefig(fig_name, dpi=300) # close figure plt.close(fig) # back to classic plot style plt.style.use('classic')
#
[docs] def plot_histogram_table(use, thermal_property, title, fig_name, factor=1e3, statistics=[], figsize=(30, 25)): """ Plots a histogram showing the values of the thermal properties for all buildings in the city (only residential). A histogram per year construction class and building type is shown. """ thermal_property = np.array(thermal_property) if use == 3: # RESIDENTIAL # define figures and axes fig, ax = plt.subplots(10, 4, figsize=figsize, tight_layout=True) # Title fig.suptitle(title) # Subplots for iii in range(10): for jjj in range(4): # histogram if thermal_property[iii][jjj].size != 0: ax[iii, jjj].hist(thermal_property[iii][jjj] / factor, color=(0.8, 0.8, 0.8)) # mean mean = (thermal_property[iii][jjj] / factor).mean() ax[iii, jjj].axvline(mean, color='b', linestyle='dashed', linewidth=2) # statistics if statistics != []: stat = (statistics[iii][jjj]).mean() ax[iii, jjj].axvline(stat, color='r', linestyle='dashed', linewidth=2) else: # NON-RESIDENTIAL # define figures and axes fig, ax = plt.subplots(5, 1, tight_layout=True) # Title fig.suptitle(title) # Subplots for iii in range(5): # plot if thermal_property[iii].size != 0: ax[iii].hist(thermal_property[iii] / factor, color=(0.8, 0.8, 0.8)) # mean mean = (thermal_property[iii] / factor).mean() ax[iii].axvline(mean, color='b', linestyle='dashed', linewidth=2) # statistics if statistics != []: stat = (statistics[iii]).mean() ax[iii].axvline(stat, color='r', linestyle='dashed', linewidth=2) # save figure fig.savefig(fig_name, dpi=300) # close figure plt.close(fig)
#
[docs] def plot_imshow_comparison(use, sim_stock, stat_stock, fig_name, cmap='RdBu'): """ Shows a figure with two tables: Left The distribution of residential buildings in the diff categories (year_class, btype) according to the statistics used to generate the synthetic building stock Right The distribution of residential buildings in the diff categories (year_class, btype) in the synthetic building stock """ # Ticks if use == 3: # RESIDENTIAL xticks_value = [0, 1, 2, 3] xticks_label = ['SFH', 'TH', 'MFH', 'AB'] yticks_value = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] yticks_label = ['<1859', '1860-1918', '1919-1948', '1949-1957', '1958-1968', '1969-1978', '1979-1983', '1984-1994', '1995-2001', '2002-2009'] max = 0.1 else: xticks_value = [0.5] xticks_label = ['All'] yticks_value = [0, 1, 2, 3, 4] yticks_label = ['<1918', '1919-1976', '1977-1983', '1984-1994', '>1995'] max = 0.25 # create [5,2] array to plot # 1D arrays cannot be used with plt.imshow() stat_stock = np.array([stat_stock, stat_stock]).transpose() sim_stock = np.array([sim_stock, sim_stock]).transpose() # define figure and axes fig, ax = plt.subplots(1, 2, subplot_kw={'xticks': xticks_value, 'yticks': yticks_value}, sharey=True) # Subplots # Ax1 - Building stock from statistics im = ax[0].imshow(stat_stock, interpolation='none', cmap=cmap, vmin=0, vmax=max, aspect='equal') ax[0].set_title('Statistics') ax[0].set_xticklabels(xticks_label) ax[0].set_yticklabels(yticks_label) # Ax2 - Building stock from simulation ax[1].imshow(sim_stock, interpolation='none', cmap=cmap, vmin=0, vmax=max, aspect='equal') ax[1].set_title('Simulation') ax[1].set_xticklabels(xticks_label) ax[1].set_yticklabels(yticks_label) # Colorbar fig.colorbar(im, ax=ax.ravel().tolist()) # save figure fig.savefig(fig_name, dpi=300) # close figure plt.close(fig)
#
[docs] def plot_typical_days(days_in_year, data_in_days, Z, number_of_clusters, min_distance_day, avg_day, clusters, clusters_per_month, month_names, timeseries_min, timeseries_avg, result_dir): """ Figures: calculation of typical days """ if not os.path.exists('{}/TypicalDays'.format(result_dir)): os.makedirs('{}/TypicalDays'.format(result_dir)) # Daily temperature profiles # -------------------------- fig, ax = plt.subplots() plt.title('Daily temperature profiles') plt.xlabel('Time [h]') plt.ylabel('Ambient temperature [degC]') plt.xticks(np.arange(24, )) ax.set_ylim(-15, 35) ax.set_xlim(0, 23) ax.grid(color='gray', linestyle='--', linewidth=0.5) for day in range(days_in_year): plt.plot(data_in_days[day, :], linewidth=1) ## fig_name = '{}/TypicalDays/DailyTemperatureProfiles.png'.format(result_dir) ## save figure fig.savefig(fig_name, dpi=300) ## close figure plt.close(fig) # Dendogram # --------- fig, ax = plt.subplots() plt.title('Hierarchical clustering dendrogram') plt.ylabel('distance') # plt.xlabel('sample index') dendrogram( Z, truncate_mode='lastp', p=number_of_clusters, leaf_rotation=90., # rotates the x axis labels leaf_font_size=8., # font size for the x axis labels ) # plt.xticks([]) ## fig_name = '{}/TypicalDays/Dendogram.png'.format(result_dir) ## save figure fig.savefig(fig_name, dpi=300) ## close figure plt.close(fig) # Time series # ----------- fig, ax = plt.subplots(2, int(np.ceil(number_of_clusters / 2.))) ax = ax.ravel() for c in range(1, number_of_clusters + 1): indices_in_cluster = np.where(clusters == c)[0] ax[c - 1].set_title('Cluster ' + str(c)) # Historical days for day in indices_in_cluster: if day >= 91 and day < 182: # Spring rgb_color = (155 / 255., 153 / 255., 0.) elif day >= 182 and day < 274: # Summer rgb_color = (1., 0.5, 0.) elif day >= 274 and day < 335: # Autumn rgb_color = (0., 153 / 255., 153 / 255.) else: # Winter rgb_color = (0., 101 / 255., 189 / 255.) ax[c - 1].plot(np.arange(24), data_in_days[day, :], color=rgb_color) ## plot average day ax[c - 1].plot(np.arange(24), avg_day[c - 1, :], 'k--') ## plot day with minimum distance ax[c - 1].plot(np.arange(24), min_distance_day[c - 1, :], 'k-') ax[c - 1].set_ylim(-15, 35) ax[c - 1].set_xlim(0, 23) ## fig_name = '{}/TypicalDays/Clusters_TimeSeries.png'.format(result_dir) ## save figure fig.savefig(fig_name, dpi=300) ## close figure plt.close(fig) # Monthly share # ------------- cm_subsection = np.linspace(0., 1., number_of_clusters) # Colors = [cm.jet(x) for x in cm_subsection][::-1] # Hot first Colors = [cm.jet(x) for x in cm_subsection] # Cold first fig, ax = plt.subplots() plt.title('Clusters (typical days) by month') plt.ylabel('') plt.xlabel('') for c in range(number_of_clusters): if c == 0: plt.bar(np.arange(14), clusters_per_month[c], color=Colors[c]) else: plt.bar(np.arange(14), clusters_per_month[c], color=Colors[c], bottom=np.cumsum(clusters_per_month, axis=0)[c - 1]) ax.set_xticks(np.arange(14)) ax.set_xticklabels(month_names) ## fig_name = '{}/TypicalDays/Clusters_SharePerMonth.png'.format(result_dir) ## save figure fig.savefig(fig_name, dpi=300) ## close figure plt.close(fig) # TypicalDays # ------------ fig, ax = plt.subplots() plt.title('Typical days') plt.xlabel('Time [h]') plt.ylabel('Ambient temperature [degC]') # plt.xticks(np.arange(24 * number_of_clusters,)) ax.grid(color='gray', linestyle='--', linewidth=0.5) plt.plot(timeseries_min, 'k-', linewidth=1) # Min distance plt.plot(timeseries_avg, 'k--', linewidth=1) # Average plt.legend(['Min distance', 'Average']) ## fig_name = '{}/TypicalDays/TypicalDays.png'.format(result_dir) ## save figure fig.savefig(fig_name, dpi=300) ## close figure plt.close(fig)