import os
import numpy as np
import matplotlib.pyplot as plt
[docs]
def get_textsize_paper() -> int:
"""Getting the fontsize (best practice) for publishing in papers"""
return 14
[docs]
def get_plot_color_inactive() -> str:
"""Getting the color for plotting non-spike activity in transient plots"""
return '#929591'
[docs]
def get_plot_color(idx: int) -> str:
"""Getting the color string"""
sel_color = ['k', 'r', 'b', 'g', 'y', 'c', 'm', 'gray']
return sel_color[idx % len(sel_color)]
[docs]
def get_plot_marker(idx: int) -> str:
"""Getting the marker for plotting"""
sel_marker = '.+x_'
return sel_marker[idx % len(sel_marker)]
[docs]
def cm_to_inch(value: float) -> float:
"""Translation figure size"""
return value / 2.54
[docs]
def scale_auto_value(data: np.ndarray | float) -> [float, str]:
"""Getting the scaling value and corresponding string notation for unit scaling in plots
Args:
data: Array or value for calculating the SI scaling value
Returns:
Tuple with [0] = scaling value and [1] = SI pre-unit
"""
ref_dict = {'T': -4, 'G': -3, 'M': -2, 'k': -1, '': 0, 'm': 1, 'µ': 2, 'n': 3, 'p': 4, 'f': 5}
value = np.max(np.abs(np.abs(data))) if isinstance(data, np.ndarray) else data
str_value = str(value).split('.')
digit = 0
if 'e' not in str_value[1]:
if not str_value[0] == '0':
# --- Bigger Representation
sys = -np.floor(len(str_value[0]) / 3)
else:
# --- Smaller Representation
for digit, val in enumerate(str_value[1], start=1):
if '0' not in val:
break
sys = np.ceil(digit / 3)
else:
val = int(str_value[1].split('e')[-1])
sys = -np.floor(abs(val) / 3) if np.sign(val) == 1 else np.ceil(abs(val) / 3)
scale = 10 ** (sys * 3)
units = [key for key, div in ref_dict.items() if sys == div][0]
return scale, units
[docs]
def translate_unit_to_scale_value(unit_str: str, pos: int) -> float:
"""Translating the unit of a value from string to float
:param unit_str: String representation of the input value
:param pos: Index of scaling value in string
:return: Scaled value
"""
ref_dict = {'T': 1e12, 'G': 1e9, 'M': 1e6, 'k': 1e3, ' ': 1e0,
'm': 1e-3, 'µ': 1e-6, 'u': 1e-6, 'n': 1e-9, 'p': 1e-12, 'f': 1e-15}
check = unit_str[pos] if not len(unit_str) == 1 else unit_str
value = [val for key, val in ref_dict.items() if key == check]
return value[0]
def _get_median(parameter: list) -> float:
"""Calculating the median of list input"""
param = np.zeros(shape=(len(parameter), ), dtype=float)
for idx, val in enumerate(parameter):
param[idx] = np.median(val)
return float(np.median(param))
def _get_mean(parameter: list) -> float:
"""Calculating the mean of list input"""
param = np.zeros(shape=(len(parameter), ), dtype=float)
for idx, val in enumerate(parameter):
param[idx] = np.mean(val)
return float(np.mean(param))
def _autoscale(ax=None, axis: str='y', margin: float=0.1):
"""Autoscales the x or y axis of a given matplotlib ax object
to fit the margins set by manually limits of the other axis,
with margins in fraction of the width of the plot
Defaults to current axes object if not specified."""
if ax is None:
ax = plt.gca()
newlow, newhigh = np.inf, -np.inf
for artist in ax.collections + ax.lines:
x,y = _get_xy(artist)
if axis == 'y':
setlim = ax.set_ylim
lim = ax.get_xlim()
fixed, dependent = x, y
else:
setlim = ax.set_xlim
lim = ax.get_ylim()
fixed, dependent = y, x
low, high = _calculate_new_limit(fixed, dependent, lim)
newlow = low if low < newlow else newlow
newhigh = high if high > newhigh else newhigh
margin = margin*(newhigh - newlow)
setlim(newlow-margin, newhigh+margin)
def _calculate_new_limit(fixed, dependent, limit):
"""Calculates the min/max of the dependent axis given a fixed axis with limits"""
if len(fixed) > 2:
mask = (fixed > limit[0]) & (fixed < limit[1])
window = dependent[mask]
low, high = window.min(), window.max()
else:
low = dependent[0]
high = dependent[-1]
if low == 0.0 and high == 1.0:
# This is a axhline in the autoscale direction
low = np.inf
high = -np.inf
return low, high
def _get_xy(artist):
"""Gets the xy coordinates of a given artist"""
if "Collection" in str(artist):
x, y = artist.get_offsets().T
elif "Line" in str(artist):
x, y = artist.get_xdata(), artist.get_ydata()
else:
raise ValueError("This type of object isn't implemented yet")
return x, y