# -*- coding: utf-8 -*-
"""
Plotting utilities
"""
from glob import glob
import pandas as pd
import os
import logging
import seaborn as sns
import matplotlib.pyplot as plt
from osos import DATA_DIR, PLOT_DIR
sns.set_style("darkgrid")
logger = logging.getLogger(__name__)
[docs]class Plotting:
"""OSOS plotting utilities for auto-plotting of usage data."""
# common aliases and capitalization conventions for plot titles
# format is all lower case keys mapped to desired alias in the value
ALIASES = {'rev': 'reV',
'revx': 'reVX',
'pysam': 'PySAM',
}
[docs] @staticmethod
def plot_metric(df, metric, cumulative=False, ylabel=None, figsize=(10, 5),
save_path=None, show=True, close=True):
"""Plot a osos metric from an osos dataframe.
Parameters
----------
df : pd.DataFrame
OSOS data timeseries dataframe, likely from the repository DATA_DIR
metric : str
Metric to plot in the dataframe. Must be one of the column titles.
cumulative : bool
Flag to plot the cumulative sum of the metric.
ylabel : str
Optional y axis label. If None the metric will be used.
save_path : str | None
Filepath to save figure to (optional).
show : bool
Flag to show / display figure (should be false for automated calls)
close : bool
Flag to close figure after saving/showing
Returns
-------
ax : matplotlib.axes._subplots.AxesSubplot
AxesSubplot object generated by matplotlib
"""
if metric not in df:
msg = ('Could not find "{}", available keys: {}'
.format(metric, df.columns.values.tolist()))
raise KeyError(msg)
fig, ax = plt.subplots(1, 1, figsize=figsize)
data = df[metric].astype(float)
if cumulative:
data = data.cumsum()
data.plot(ax=ax)
_ = plt.xticks(rotation=45)
if ylabel is not None:
ax.set_ylabel(ylabel)
if save_path is not None:
fig.savefig(save_path, bbox_inches='tight')
logger.info('Saved: {}'.format(save_path))
if show:
plt.show()
if close:
plt.close()
return ax
[docs] @classmethod
def auto_plot(cls, metric, cumulative=False, ylabel=None,
source_dir=DATA_DIR, save_dir=PLOT_DIR):
"""Auto plot a single metric for all osos datasets in the osos
source_dir path
Parameters
----------
metric : str
Metric to plot in the dataframe. Must be one of the column titles.
cumulative : bool
Flag to plot the cumulative sum of the metric.
ylabel : str
y axis label for all plots. Can include format string {name} that
will be replaced with the repo name from the data filename. If
None, the ylabel will just be the metric.
source_dir : str
Directory to look for osos csv's. This function will try to plot
the desired metric from all csv's in this directory.
save_dir : str
Directory to save the plots. Will be created if it doesnt exist.
"""
fps = glob(source_dir + '/*.csv')
names = [os.path.basename(fp).replace('.csv', '') for fp in fps]
if not os.path.exists(save_dir):
os.makedirs(save_dir)
for name, fp in zip(names, fps):
name = name.lower()
save_path = os.path.join(save_dir, f'{name}_{metric}.png')
if cumulative:
save_path = save_path.replace('.png', '_cumulative.png')
if name in cls.ALIASES:
name = cls.ALIASES[name]
else:
name = name.upper()
i_ylabel = ylabel
if isinstance(i_ylabel, str) and '{name}' in i_ylabel:
i_ylabel = i_ylabel.format(name=name)
df = pd.read_csv(fp, index_col=0, parse_dates=True)
try:
cls.plot_metric(df, metric, cumulative=cumulative,
save_path=save_path, ylabel=i_ylabel,
show=False, close=True)
except KeyError:
logger.info(f'Could not plot metric "{metric}" for "{name}".')