import types
import numpy as np
import matplotlib.pyplot as plt
from pyH2A.Utilities.output_utilities import make_bold, millify, bottom_offset, Figure_Lean
from pyH2A.Discounted_Cash_Flow import Discounted_Cash_Flow
[docs]class Cost_Contributions_Analysis:
'''Reading cost contributions from DCF output and plotting it.
Notes
-----
`Cost_Contributions_Analysis` does not require any input, it is sufficient
to include "# Cost_Contributions_Analysis" in input file.
Contributions for plotting have to provided as a dictionary with three components:
`Data` containing the name and value for each contribution.
`Total` containing the total value
`Table Group`, containing the name of overarching group of values, which are shown.
Dictionaries with this structure can be automatically generated by ``sum_all_tables``
function.
If the name of a contribution contains a '-', the string will be split and only the part after the
'-' will be displayed.
'''
def __init__(self, input_file):
self.base_case = Discounted_Cash_Flow(input_file, print_info = False)
[docs] def cost_breakdown_plot(self, ax = None, figure_lean = True,
plugin = None, plugin_property = None,
label_offset = 5.5, x_label_string = 'Cost / USD',
x_label_string_H2 = r'Levelized cost / USD per kg $H_{2}$',
plot_kwargs = {}, **kwargs):
'''Plotting cost breakdown plot.
Parameters
----------
ax : matplotlib.axes, optional
Axes object in which plot is drawn. Default is None, creating new plot.
figure_lean : bool, optional
If figure_lean is True, matplotlib.fig object is returned.
plugin : str or None, optional
Selection of plugin from which contributions data is to be read. If None,
defaults to overall H2 cost contributions.
plugin_property: str or None, optional
Specific property of plugin from which contributions data is to be read.
label_offset : float, optional
Offset for contributions labels.
x_label_string : str, optional
String for x axis label.
x_label_string_H2 : str, optional
String for x axis label when overall H2 cost breakdown is plotted
plot_kwargs: dict, optional
Dictionary containing optional keyword arguments for
:func:`~pyH2A.Utilities.output_utilities.Figure_Lean`, has priority over `**kwargs`.
**kwargs:
Additional `kwargs` passed to
:func:`~pyH2A.Utilities.output_utilities.Figure_Lean`
Returns
-------
figure : matplotlib.fig or None
matplotlib.fig is returned if `figure_lean` is True.
Notes
-----
Names of contributions are split at '-' symbols and only the last
part is displayed. For example: `Direct Capital Costs - Installation`
is displayed only as `Installation`.
'''
kwargs = {**{'left': 0.4, 'top': 0.96,
'name': 'Cost_Breakdown_Plot'},
**kwargs, **plot_kwargs}
if ax is None:
figure = Figure_Lean(**kwargs)
ax = figure.ax
if plugin is None:
self.contributions = self.base_case.contributions
self.data = self.base_case.contributions['Data']
else:
selected_plugin = self.base_case.plugs[plugin]
self.contributions = getattr(selected_plugin, plugin_property)
self.data = self.contributions['Data']
sorted_keys = sorted(self.data, key = self.data.get)
sorted_contributions = {}
for key in sorted_keys:
sorted_contributions[key] = self.data[key]
cmap = plt.get_cmap('plasma')
label_offset = self.contributions['Total'] / label_offset
for counter, key in enumerate(sorted_contributions):
if '-' in key:
name = key.split('-')[1].strip(' ')
else:
name = key
value = sorted_contributions[key]
color_value = counter / len(sorted_contributions)
ax.barh(name, sorted_contributions[key],
color = cmap(color_value), zorder = 5)
ax.annotate(millify(value), xy = (max(value, 0) + label_offset, counter),
va = 'center', ha = 'center')
ax.barh(make_bold(self.contributions['Table Group']),
self.contributions['Total'],
color = 'darkgreen', zorder = 5)
ax.annotate(millify(self.contributions['Total']),
xy = (self.contributions['Total'] + label_offset,
len(sorted_contributions)),
va = 'center', ha = 'center')
if self.contributions['Table Group'] == 'Total cost of hydrogen':
x_label_string = x_label_string_H2
ax.set_xlabel(x_label_string)
xlim = np.asarray(ax.get_xlim())
xlim[1] += 2 * label_offset
ax.set_xlim(xlim)
ax.ticklabel_format(axis = 'x', style = 'sci', scilimits = (0,0), useMathText = True)
ax.xaxis._update_offset_text_position = types.MethodType(bottom_offset, ax.xaxis)
ax.grid(color = 'grey', linestyle = '--', linewidth = 0.2, zorder = 0)
if figure_lean is True:
figure.execute()
return figure.fig