# SPDX-FileCopyrightText: 2020/2021 Jonathan Pieper <ody55eus@mailbox.org>
#
# SPDX-License-Identifier: GPL-3.0-or-later
# -*- coding: utf-8 -*-
"""
Main parent class for all plotting classes.
"""
import logging # System Modules
import os
# Basic Plotting libraries
import matplotlib
from matplotlib import cm
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
[docs]class PlottingClass(object):
"""Defines the basic plotting style."""
def __init__(self, **style):
"""
Args:
**style:
"""
default_style = {
'dpi': 300,
'figure.autolayout': False,
'figsize': (8, 6),
'axes.labelsize': 18,
'axes.titlesize': 20,
'font.size': 16,
'lines.linewidth': 2.0,
'lines.markersize': 8,
'legend.fontsize': 14,
'mpl_style': False,
'latex': True,
'default_cm': cm.Blues,
}
self.name = 'Default Plotting Class'
self.style = default_style
self.set_style(**style)
get = lambda self, *key: self.style.get(*key)
__repr__ = lambda self: '%s\n' % self.name
__str__ = lambda self: '%s\n' % self.name + \
'\n'.join(['%s:\t%s' % (key, val) for key, val in self.style.items()])
[docs] def update(self, other):
"""
Args:
other:
"""
self.style.update(other)
def __setitem__(self, key, value):
"""
Args:
key:
value:
"""
self.update(dict(key=value))
def __add__(self, other):
self.update(other)
# Set Plotting Style
[docs] def set_style(self, **style):
"""
Sets the Style for plots
:param size: A dictionary of parameters or the name of a preconfigured set.
:type size: dict, None, or one of {paper, notebook, talk, poster}
:param style:
:type style: dict, None, or one of {darkgrid, whitegrid, dark, white, ticks}
:param default: if True it sets default
:code:`size=talk` and
:code:`style=whitegrid`
:type default: bool
:param notebook: if True it sets default
:code:`size=notebook` and
:code:`style=ticks`
:type notebook: bool
Returns
-------
None.
"""
self.style.update(style)
if self.get('default'):
def_size = 'talk'
def_style = 'whitegrid'
elif self.get('notebook'):
def_size = 'notebook'
def_style = 'ticks'
else:
def_size = 'talk'
def_style = 'whitegrid'
sns.set(self.get('size', def_size),
self.get('style', def_style),
self.get('palette', 'deep'),
self.get('font', 'sans-serif'),
self.get('font-scale', 1))
if style.get('grid'):
plt.rcParams['axes.grid'] = True
plt.rcParams['grid.linestyle'] = '--'
latex = 'latex' in self.style
plt.rcParams['text.usetex'] = latex
if latex: # True activates latex output in fonts!
plt.rcParams[
'text.latex.preamble'] = ''
if self.get('set_mpl_params', False):
params = style.get('mpl_params', {
'figure.dpi': self.get('dpi', 300),
'savefig.dpi': self.get('dpi', 300),
'figure.figsize': self.get('figsize'),
'figure.autolayout': False,
'axes.labelsize': 18,
'axes.titlesize': 20,
'font.size': 16,
'lines.linewidth': 2.0,
'lines.markersize': 8,
'legend.fontsize': 14,
'figure.subplot.hspace': 0.3,
'figure.subplot.wspace': 0.3,
'savefig.transparent': False,
'savefig.bbox': 'tight',
'savefig.pad_inches': 0.1,
})
update_keys = ['figure.autolayout',
'axes.labelsize',
'axes.titlesize',
'font.size',
'lines.linewidth',
'lines.markersize',
'legend.fontsize']
params.update({
update_keys[key]: self.get(update_keys[key]) \
for key in np.argwhere([_ in style \
for _ in update_keys]).ravel()
})
matplotlib.rcParams.update(params)
if self.get('mpl_style'):
matplotlib.style.use(self.get('mpl_style'))
[docs] def get_style(self, custom=None):
"""
Args:
custom:
"""
if custom:
return plt.style.context(custom)
return plt.style.context(self.get('mpl_style'))
[docs] def set_plot_settings(self, **kwargs):
"""
Args:
**kwargs:
"""
plt.xscale(kwargs.get('xscale', 'log'))
plt.yscale(kwargs.get('yscale', 'log'))
xmin, xmax = kwargs.get('xlim', (None, None))
ymin, ymax = kwargs.get('ylim', (None, None))
if xmin:
plt.xlim(xmin, xmax)
if ymin:
plt.ylim(ymin, ymax)
if not kwargs.get('legend_settings'):
plt.legend(loc=kwargs.get('legend_location', 'best'))
else:
plt.legend(**kwargs.get('legend_settings'))
if kwargs.get('grid'):
plt.grid(b=True, **kwargs['grid'])
title = kwargs.get('title')
if title:
plt.title(title)
xlabel = kwargs.get('xlabel', '$f$ [Hz]')
ylabel = kwargs.get('ylabel', '$S_{V_H}$ [${V^2}$/{Hz}]')
plt.xlabel(xlabel)
plt.ylabel(ylabel)
[docs] def draw_oneoverf(self, ax, **kwargs):
# Draw 1/f
"""
Args:
ax:
**kwargs:
"""
xmin = kwargs.get('xmin', .1)
ymin = kwargs.get('ymin', 1e-6)
factor = kwargs.get('factor', 10)
alpha = kwargs.get('alpha', 1)
if kwargs.get('plot_label'):
label = kwargs.get('plot_label')
elif alpha == 1:
label = '$1/f$'
else:
label = '$1/f^%s$' % alpha
mean_x = kwargs.get('mean_x', (xmin * np.sqrt(factor)))
mean_y = kwargs.get('mean_y', (ymin / (factor ** (alpha / 2))))
if not (kwargs.get('disable')):
ax.plot([xmin, xmin * factor], [ymin, ymin / (factor ** alpha)],
kwargs.get('plot_style', 'k--'), label=label, linewidth=2)
ax.annotate(label, (mean_x, mean_y),
color=kwargs.get('an_color', 'black'),
size=kwargs.get('an_size', 16))
[docs] def save_plot(self, fname, fext='png'):
"""Saves the current plot as file.
Args:
fname (str): Filename
fext (str): Extension
Returns:
None
"""
base = os.path.basename(fname)
if not os.path.exists(base):
os.makedirs(base)
if fext == 'pgf':
matplotlib.rcParams.update({
"pgf.texsystem": "pdflatex",
'font.family': 'serif',
'text.usetex': True,
'pgf.rcfonts': False,
'text.latex.preamble': r'\usepackage[utf8]{inputenc}\DeclareUnicodeCharacter{2212}{-}'
})
plt.savefig('%s.%s' % (fname, fext), backend='pgf')
plt.show()
else:
plt.savefig('%s.%s' % (fname, fext))