Files
paper_2025/python/fig_invariance_log-hp.py

133 lines
5.0 KiB
Python

import numpy as np
import matplotlib.pyplot as plt
from itertools import product
def prepare_fig(nrows, ncols, width=8, height=None, rheight=2,
left=0.01, right=0.95, bottom=0.01, top=0.95,
wspace=0.4, hspace=0.4):
if height is None:
height = rheight * nrows
fig = plt.figure(figsize=(width, height))
grid = fig.add_gridspec(nrows=nrows, ncols=ncols, wspace=wspace, hspace=hspace,
left=left, right=right, top=top, bottom=bottom)
axes = np.zeros((nrows, ncols), dtype=object)
for i, j in product(range(nrows), range(ncols)):
axes[i, j] = fig.add_subplot(grid[i, j])
axes[i, j].set_facecolor('none')
return fig, axes
def xlimits(ax, time, minval=None, maxval=None, pad=0.05):
limits = [minval, maxval]
if minval is None:
limits[0] = time[0]
if maxval is None:
limits[1] = time[-1]
if pad is not None and minval is None:
limits[0] -= (limits[1] - limits[0]) * pad
if pad is not None and maxval is None:
limits[1] += (limits[1] - limits[0]) * pad
return ax.set_xlim(limits)
def ylimits(ax, signal, minval=None, maxval=None, pad=0.05):
limits = [minval, maxval]
if minval is None:
limits[0] = signal.min()
if maxval is None:
limits[1] = signal.max()
if pad is not None and minval is None:
limits[0] -= (limits[1] - limits[0]) * pad
if pad is not None and maxval is None:
limits[1] += (limits[1] - limits[0]) * pad
return ax.set_ylim(limits)
def ylabel(ax, label, x=-0.23, fontsize=20):
ax.set_ylabel(label, fontsize=fontsize, rotation=0, ha='left', va='center')
ax.yaxis.set_label_coords(x, 0.5)
return None
def super_xlabel(label, fig, high_ax, low_ax, y=0.005, **kwargs):
x = (low_ax.get_position().x0 + high_ax.get_position().x1) / 2
fig.supxlabel(label, x=x, y=y, **kwargs)
return None
def super_ylabel(label, fig, high_ax, low_ax, x=0.005, **kwargs):
y = (low_ax.get_position().y0 + high_ax.get_position().y1) / 2
fig.supylabel(label, x=x, y=y, **kwargs)
return None
def hide_axis(ax, side='bottom'):
ax.spines[side].set_visible(False)
params = {side: False, 'label' + side: False}
ax.tick_params(axis='x' if side in ['top', 'bottom'] else 'y',
which='both', **params)
return None
def plot_line(ax, time, signal, ymin=None, ymax=None, xmin=None, xmax=None,
xpad=None, ypad=0.05, yloc=None, **kwargs):
handles = ax.plot(time, signal, **kwargs)
xlimits(ax, time, minval=xmin, maxval=xmax, pad=xpad)
ylimits(ax, signal, minval=ymin, maxval=ymax, pad=ypad)
ax.yaxis.set_major_locator(plt.MultipleLocator(yloc))
return handles
def plot_barcode(ax, time, binary, offset=0.5, xmin=None, xmax=None, **kwargs):
if xmin is None:
xmin = time[0]
if xmax is None:
xmax = time[-1]
lower, upper, handles = 0, 1, []
for i in range(binary.shape[1]):
h = ax.fill_between(time, lower, upper, where=binary[:, i], **kwargs)
handles.append(h)
if i < binary.shape[1] - 1:
lower += offset + 1
upper += offset + 1
xlimits(ax, time, minval=xmin, maxval=xmax)
ax.set_ylim(0, upper)
hide_axis(ax, 'bottom')
hide_axis(ax, 'left')
return handles
def indicate_zoom(fig, high_ax, low_ax, zoom_abs, **kwargs):
y0 = low_ax.get_position().y0
y1 = high_ax.get_position().y1
transform = low_ax.transData + fig.transFigure.inverted()
x0 = transform.transform((zoom_abs[0], 0))[0]
x1 = transform.transform((zoom_abs[1], 0))[0]
rect = plt.Rectangle((x0, y0), x1 - x0, y1 - y0,
transform=fig.transFigure, **kwargs)
fig.add_artist(rect)
return None
def assign_colors(handles, types, colors):
for handle, type_id in zip(handles, types):
handle.set_color(colors[str(int(type_id))])
return None
def reorder_traces(handles, signal, zlow=2, zhigh=2.5):
inds = np.argsort(signal.std(axis=0))
zorders = np.linspace(zlow, zhigh, len(inds))[::-1]
for ind, z in zip(inds, zorders):
handles[ind].set_zorder(z)
return None
def choose_kernels(kern_specs, features, kern_types, per_type=2, thresh=0.01):
mean_feat = features.mean(axis=0)
feat_diff = np.abs(mean_feat[:, None] - mean_feat[None, :])
feat_diff[features.max(axis=0) < thresh, :] = np.nan
feat_diff = np.nanmean(feat_diff, axis=0)
ranking = np.argsort(feat_diff)
kern_inds = []
for type_id in kern_types:
type_inds = np.nonzero(kern_specs[:, 0] == type_id)[0]
rank_inds = np.nonzero(np.isin(ranking, type_inds))[0][-per_type:]
kern_inds.extend(ranking[rank_inds])
return np.array(kern_inds)
def letter_subplots(axes, labels='abcd', x=0.02, y=1, ha='left', va='bottom',
fontsize=16, fontweight='bold', **kwargs):
for ax, label in zip(axes, labels):
ax.text(x, y, label, transform=ax.transAxes, ha=ha, va=va,
fontsize=fontsize, fontweight=fontweight, **kwargs)
return None