Seriously, no idea. Wild amount of changes. Good luck.

This commit is contained in:
j-hartling
2026-04-17 17:19:30 +02:00
parent 36ac504efa
commit 3b4b7f2161
40 changed files with 2067 additions and 672 deletions

View File

@@ -58,19 +58,19 @@ def side_distributions(axes, snippets, inset_bounds, thresh, nbins=1000,
# GENERAL SETTINGS:
target = 'Omocestus_rufipes'
data_paths = search_files(target, incl='noise', dir='../data/inv/thresh_lp/')
example_file = 'Omocestus_rufipes_DJN_32-40s724ms-48s779ms'
data_path = search_files(example_file, incl='noise', dir='../data/inv/thresh_lp/')[0]
stages = ['conv', 'bi', 'feat']
load_kwargs = dict(
files=stages,
keywords=['scales', 'snip', 'measure', 'thresh']
)
save_path = None#'../figures/fig_invariance_thresh_lp_single.pdf'
save_path = '../figures/fig_invariance_thresh_lp_single.pdf'
exclude_zero = True
# GRAPH SETTINGS:
fig_kwargs = dict(
figsize=(32/2.54, 16/2.54),
figsize=(32/2.54, 32/2.54),
)
super_grid_kwargs = dict(
nrows=None,
@@ -140,6 +140,8 @@ lw = dict(
bi=0.1,
feat=3,
big=4,
kern=2.5,
plateau=1.5,
)
xlabels = dict(
alpha='scale $\\alpha$',
@@ -216,6 +218,10 @@ letter_big_kwargs = dict(
va='top',
fontsize=fs['letter'],
)
kern_kwargs = dict(
c='k',
lw=lw['kern'],
)
dist_kwargs = dict(
c='k',
lw=1,
@@ -257,171 +263,198 @@ plateau_settings = dict(
last=True,
condense=None,
)
plateau_line_kwargs = dict(
lw=lw['plateau'],
ls='--',
zorder=1,
)
plateau_dot_kwargs = dict(
marker='o',
markersize=8,
markeredgewidth=1,
clip_on=False,
)
zoom_rel = np.array([0.5, 0.515])
# SUBSET SETTINGS:
kern_specs = np.array([
[1, 0.008],
[2, 0.004],
[3, 0.002],
])[np.array([1])]
zoom_rel = np.array([0.5, 0.515])
# EXECUTION:
for data_path in data_paths:
print(f'Processing {data_path}')
print(f'Processing {data_path}')
# Load invariance data:
noise_data, config = load_data(data_path, **load_kwargs)
pure_data, _ = load_data(data_path.replace('noise', 'pure'), **load_kwargs)
# Load invariance data:
noise_data, config = load_data(data_path, **load_kwargs)
pure_data, _ = load_data(data_path.replace('noise', 'pure'), **load_kwargs)
# Unpack shared variables:
scales = noise_data['scales']
plot_scales = noise_data['example_scales']
thresh_rel = noise_data['thresh_rel']
thresh_abs = noise_data['thresh_abs']
# Unpack shared variables:
scales = noise_data['scales']
plot_scales = noise_data['example_scales']
thresh_rel = noise_data['thresh_rel']
thresh_abs = noise_data['thresh_abs']
# Reduce to kernel subset and crop to zoom frame:
t_full = np.arange(noise_data['snip_conv'].shape[0]) / config['env_rate']
zoom_abs = zoom_rel * t_full[-1]
zoom_inds = (t_full >= zoom_abs[0]) & (t_full <= zoom_abs[1])
kern_ind = find_kern_specs(config['k_specs'], kerns=kern_specs)[0]
noise_data['snip_inv'] = noise_data['snip_inv'][zoom_inds, :]
noise_data['snip_conv'] = noise_data['snip_conv'][zoom_inds, kern_ind, :]
noise_data['snip_bi'] = noise_data['snip_bi'][zoom_inds, kern_ind, :, :]
noise_data['snip_feat'] = noise_data['snip_feat'][zoom_inds, kern_ind, :, :]
noise_data['measure_feat'] = noise_data['measure_feat'][:, kern_ind, :]
pure_data['measure_feat'] = pure_data['measure_feat'][:, kern_ind, :]
thresh_abs = thresh_abs[:, kern_ind]
t_full = np.arange(noise_data['snip_conv'].shape[0]) / config['env_rate']
if exclude_zero:
# Reduce to nonzero scales:
nonzero_inds = scales > 0
scales = scales[nonzero_inds]
noise_data['measure_inv'] = noise_data['measure_inv'][nonzero_inds]
noise_data['measure_feat'] = noise_data['measure_feat'][nonzero_inds, :]
pure_data['measure_feat'] = pure_data['measure_feat'][nonzero_inds, :]
# Reduce to kernel subset and crop to zoom frame:
t_full = np.arange(noise_data['snip_conv'].shape[0]) / config['env_rate']
zoom_abs = zoom_rel * t_full[-1]
zoom_inds = (t_full >= zoom_abs[0]) & (t_full <= zoom_abs[1])
kern_ind = find_kern_specs(config['k_specs'], kerns=kern_specs)[0]
noise_data['snip_inv'] = noise_data['snip_inv'][zoom_inds, :]
noise_data['snip_conv'] = noise_data['snip_conv'][zoom_inds, kern_ind, :]
noise_data['snip_bi'] = noise_data['snip_bi'][zoom_inds, kern_ind, :, :]
noise_data['snip_feat'] = noise_data['snip_feat'][zoom_inds, kern_ind, :, :]
noise_data['measure_feat'] = noise_data['measure_feat'][:, kern_ind, :]
pure_data['measure_feat'] = pure_data['measure_feat'][:, kern_ind, :]
config['kernels'] = config['kernels'][:, kern_ind]
thresh_abs = thresh_abs[:, kern_ind]
t_full = np.arange(noise_data['snip_conv'].shape[0]) / config['env_rate']
# Get threshold-specific colors:
factors = np.linspace(*shade_factors, thresh_rel.size)
shaded = dict(
conv=shade_colors(colors['conv'], factors),
bi=shade_colors(colors['bi'], factors),
feat=shade_colors(colors['feat'], factors),
)
if exclude_zero:
# Exclude zero scale:
inds = scales > 0
scales = scales[inds]
noise_data['measure_inv'] = noise_data['measure_inv'][inds]
noise_data['measure_feat'] = noise_data['measure_feat'][inds, :]
pure_data['measure_feat'] = pure_data['measure_feat'][inds, :]
# Adjust grid parameters to loaded data:
super_grid_kwargs['nrows'] = snip_rows * thresh_rel.size + input_rows
input_grid_kwargs['ncols'] = plot_scales.size
snip_grid_kwargs['ncols'] = plot_scales.size
# Get threshold-specific colors:
factors = np.linspace(*shade_factors, thresh_rel.size)
shaded = dict(
conv=shade_colors(colors['conv'], factors),
bi=shade_colors(colors['bi'], factors),
feat=shade_colors(colors['feat'], factors),
)
# Prepare overall graph:
fig = plt.figure(**fig_kwargs)
super_grid = fig.add_gridspec(**super_grid_kwargs)
# Adjust grid parameters to loaded data:
super_grid_kwargs['nrows'] = snip_rows * thresh_rel.size + input_rows
input_grid_kwargs['ncols'] = plot_scales.size
snip_grid_kwargs['ncols'] = plot_scales.size
# Prepare input snippet axes:
input_subfig = fig.add_subfigure(super_grid[subfig_specs['input']])
input_axes = add_snip_axes(input_subfig, input_grid_kwargs).ravel()
input_axes[0].yaxis.set_major_locator(plt.MultipleLocator(yloc['inv'][0]))
input_axes[1].yaxis.set_major_locator(plt.MultipleLocator(yloc['inv'][1]))
ylabel(input_axes[0], ylabels['inv'], transform=input_subfig.transSubfigure, **ylab_snip_kwargs)
for ax, scale in zip(input_axes, plot_scales):
title_subplot(ax, f'$\\alpha={strip_zeros(scale)}$', ref=input_subfig, **title_kwargs)
letter_subplot(input_subfig, 'a', **letter_snip_kwargs)
# Prepare overall graph:
fig = plt.figure(**fig_kwargs)
super_grid = fig.add_gridspec(**super_grid_kwargs)
# Prepare snippet axes:
snip_subfigs, snip_axes = [], []
for i in range(thresh_rel.size):
subfig_spec = subfig_specs['snip'].copy()
subfig_spec[0] = slice(*(subfig_spec[0] + i * snip_rows))
snip_subfig = fig.add_subfigure(super_grid[*subfig_spec])
axes = add_snip_axes(snip_subfig, snip_grid_kwargs)
[hide_axis(ax, 'left') for ax in axes[1:, 1]]
super_ylabel(f'$\\Theta={strip_zeros(thresh_rel[i])}\\cdot\\sigma_{{\\eta}}$',
snip_subfig, axes[-1, 0], axes[0, 0], **ylab_super_kwargs)
for (ax1, ax2), stage in zip(axes[:, :2], stages):
ax1.yaxis.set_major_locator(plt.MultipleLocator(yloc[stage][0]))
ax2.yaxis.set_major_locator(plt.MultipleLocator(yloc[stage][1]))
ylabel(ax1, ylabels[stage], transform=snip_subfig.transSubfigure, **ylab_snip_kwargs)
if i == thresh_rel.size - 1:
axes[-1, -1].set_xlim(t_full[0], t_full[-1])
time_bar(axes[-1, -1], **bar_kwargs)
snip_subfigs.append(snip_subfig)
snip_axes.append(axes)
letter_subplots(snip_subfigs, 'bcd', **letter_snip_kwargs)
# Prepare input snippet axes:
input_subfig = fig.add_subfigure(super_grid[subfig_specs['input']])
input_axes = add_snip_axes(input_subfig, input_grid_kwargs).ravel()
input_axes[0].yaxis.set_major_locator(plt.MultipleLocator(yloc['inv'][0]))
input_axes[1].yaxis.set_major_locator(plt.MultipleLocator(yloc['inv'][1]))
ylabel(input_axes[0], ylabels['inv'], transform=input_subfig.transSubfigure, **ylab_snip_kwargs)
for ax, scale in zip(input_axes, plot_scales):
title_subplot(ax, f'$\\alpha={strip_zeros(scale)}$', ref=input_subfig, **title_kwargs)
letter_subplot(input_subfig, 'a', **letter_snip_kwargs)
# Prepare analysis axes:
big_subfig = fig.add_subfigure(super_grid[subfig_specs['big']])
big_grid = big_subfig.add_gridspec(**big_grid_kwargs)
# Prepare snippet axes:
snip_subfigs, snip_axes = [], []
for i in range(thresh_rel.size):
subfig_spec = subfig_specs['snip'].copy()
subfig_spec[0] = slice(*(subfig_spec[0] + i * snip_rows))
snip_subfig = fig.add_subfigure(super_grid[*subfig_spec])
axes = add_snip_axes(snip_subfig, snip_grid_kwargs)
[hide_axis(ax, 'left') for ax in axes[1:, 1]]
super_ylabel(f'$\\Theta={strip_zeros(thresh_rel[i])}\\cdot\\sigma_{{\\eta}}$',
snip_subfig, axes[-1, 0], axes[0, 0], **ylab_super_kwargs)
for (ax1, ax2), stage in zip(axes[:, :2], stages):
ax1.yaxis.set_major_locator(plt.MultipleLocator(yloc[stage][0]))
ax2.yaxis.set_major_locator(plt.MultipleLocator(yloc[stage][1]))
ylabel(ax1, ylabels[stage], transform=snip_subfig.transSubfigure, **ylab_snip_kwargs)
if i == thresh_rel.size - 1:
axes[-1, -1].set_xlim(t_full[0], t_full[-1])
time_bar(axes[-1, -1], **bar_kwargs)
snip_subfigs.append(snip_subfig)
snip_axes.append(axes)
letter_subplots(snip_subfigs, 'bcd', **letter_snip_kwargs)
alpha_ax = big_subfig.add_subplot(big_grid[0, 0])
alpha_ax.set_xlim(scales[0], scales[-1])
alpha_ax.set_xscale('symlog', linthresh=scales[scales > 0][0], linscale=0.5)
ylimits(pure_data['measure_feat'], alpha_ax, minval=0, pad=ypad['big'])
alpha_ax.yaxis.set_major_locator(plt.MultipleLocator(yloc['big']))
xlabel(alpha_ax, xlabels['alpha'], **xlab_alpha_kwargs)
ylabel(alpha_ax, ylabels['big'], transform=big_subfig.transSubfigure, **ylab_big_kwargs)
# Prepare analysis axes:
big_subfig = fig.add_subfigure(super_grid[subfig_specs['big']])
big_grid = big_subfig.add_gridspec(**big_grid_kwargs)
sigma_ax = big_subfig.add_subplot(big_grid[1, 0])
sigma_ax.set_xlim(noise_data['measure_inv'].min(), noise_data['measure_inv'].max())
# sigma_ax.set_xscale('log')
sigma_ax.set_xlim(scales[0], scales[-1])
sigma_ax.set_xscale('symlog', linthresh=scales[scales > 0][0], linscale=0.5)
ylimits(pure_data['measure_feat'], sigma_ax, minval=0, pad=ypad['big'])
sigma_ax.yaxis.set_major_locator(plt.MultipleLocator(yloc['big']))
xlabel(sigma_ax, xlabels['sigma'], **xlab_sigma_kwargs)
ylabel(sigma_ax, ylabels['big'], transform=big_subfig.transSubfigure, **ylab_big_kwargs)
alpha_ax = big_subfig.add_subplot(big_grid[0, 0])
alpha_ax.set_xlim(scales[0], scales[-1])
alpha_ax.set_xscale('symlog', linthresh=scales[scales > 0][0], linscale=0.5)
ylimits(pure_data['measure_feat'], alpha_ax, minval=0, pad=ypad['big'])
alpha_ax.yaxis.set_major_locator(plt.MultipleLocator(yloc['big']))
xlabel(alpha_ax, xlabels['alpha'], **xlab_alpha_kwargs)
ylabel(alpha_ax, ylabels['big'], transform=big_subfig.transSubfigure, **ylab_big_kwargs)
# Plot intensity-adapted snippets:
plot_snippets(input_axes, t_full, noise_data['snip_inv'],
ypad=ypad['inv'], c=colors['inv'], lw=lw['inv'])
ylimits(noise_data['snip_inv'][:, 0], input_axes[0], pad=ypad['inv'])
sigma_ax = big_subfig.add_subplot(big_grid[1, 0])
sigma_ax.set_xlim(noise_data['measure_inv'].min(), noise_data['measure_inv'].max())
sigma_ax.set_xlim(scales[0], scales[-1])
sigma_ax.set_xscale('symlog', linthresh=scales[scales > 0][0], linscale=0.5)
ylimits(pure_data['measure_feat'], sigma_ax, minval=0, pad=ypad['big'])
sigma_ax.yaxis.set_major_locator(plt.MultipleLocator(yloc['big']))
xlabel(sigma_ax, xlabels['sigma'], **xlab_sigma_kwargs)
ylabel(sigma_ax, ylabels['big'], transform=big_subfig.transSubfigure, **ylab_big_kwargs)
# Plot representation snippets per threshold:
for i, (subfig, axes) in enumerate(zip(snip_subfigs, snip_axes)):
dist_fill_kwargs['color'] = shaded['bi'][i]
# Plot intensity-adapted snippets:
plot_snippets(input_axes, t_full, noise_data['snip_inv'],
ypad=ypad['inv'], c=colors['inv'], lw=lw['inv'])
ylimits(noise_data['snip_inv'][:, 0], input_axes[0], pad=ypad['inv'])
# Plot kernel response snippets:
plot_snippets(axes[0, :], t_full, noise_data['snip_conv'], thresh=thresh_abs[i],
ypad=ypad['conv'], fill_kwargs=dist_fill_kwargs, c=shaded['conv'][i], lw=lw['conv'])
ylimits(noise_data['snip_conv'][:, 0], axes[0, 0], pad=ypad['conv'])
# Indicate kernel waveform over 1st intensity-adapted snippet:
input_axes[0].plot(config['k_times'] + 0.5 * t_full[-1], config['kernels'], **kern_kwargs)
# Plot kernel response distributions:
side_distributions(axes[0, :1], noise_data['snip_conv'][:, :1], dist_inset_bounds,
thresh_abs[i], nbins=50, fill_kwargs=dist_fill_kwargs, **dist_kwargs)
side_distributions(axes[0, 1:], noise_data['snip_conv'][:, 1:], dist_inset_bounds,
thresh_abs[i], nbins=50, fill_kwargs=dist_fill_kwargs, **dist_kwargs)
# Plot representation snippets per threshold:
for i, (subfig, axes) in enumerate(zip(snip_subfigs, snip_axes)):
dist_fill_kwargs['color'] = shaded['bi'][i]
# Plot binary snippets:
plot_bi_snippets(axes[1, :], t_full, noise_data['snip_bi'][:, :, i],
color=shaded['bi'][i], lw=lw['bi'])
# Plot kernel response snippets:
plot_snippets(axes[0, :], t_full, noise_data['snip_conv'], thresh=thresh_abs[i],
ypad=ypad['conv'], fill_kwargs=dist_fill_kwargs, c=shaded['conv'][i], lw=lw['conv'])
ylimits(noise_data['snip_conv'][:, 0], axes[0, 0], pad=ypad['conv'])
# Plot feature snippets:
handles = plot_snippets(axes[2, :], t_full, noise_data['snip_feat'][:, :, i],
ymin=0, ymax=1, c=shaded['feat'][i], lw=lw['feat'])
[set_clip_box(h[0], ax, bounds=[[0, -0.05], [1, 1.05]]) for h, ax in zip(handles, axes[2, :])]
# Plot kernel response distributions:
side_distributions(axes[0, :1], noise_data['snip_conv'][:, :1], dist_inset_bounds,
thresh_abs[i], nbins=50, fill_kwargs=dist_fill_kwargs, **dist_kwargs)
side_distributions(axes[0, 1:], noise_data['snip_conv'][:, 1:], dist_inset_bounds,
thresh_abs[i], nbins=50, fill_kwargs=dist_fill_kwargs, **dist_kwargs)
# Get threshold-specific saturation:
for i in range(thresh_rel.size):
ind = get_saturation(noise_data['measure_feat'][:, i], **plateau_settings)[1]
# Plot binary snippets:
plot_bi_snippets(axes[1, :], t_full, noise_data['snip_bi'][:, :, i],
color=shaded['bi'][i], lw=lw['bi'])
# Plot analysis results:
for ax, x in zip([alpha_ax, sigma_ax], [scales, noise_data['measure_inv']]):
# Plot pure-song analysis results:
handles = ax.plot(x, pure_data['measure_feat'], lw=lw['big'], ls='dotted')
[h.set_color(c) for h, c in zip(handles, shaded['feat'])]
# Plot feature snippets:
handles = plot_snippets(axes[2, :], t_full, noise_data['snip_feat'][:, :, i],
ymin=0, ymax=1, c=shaded['feat'][i], lw=lw['feat'])
[set_clip_box(h[0], ax, bounds=[[0, -0.05], [1, 1.05]]) for h, ax in zip(handles, axes[2, :])]
# Plot noise-song analysis results:
handles = ax.plot(x, noise_data['measure_feat'], lw=lw['big'])
[h.set_color(c) for h, c in zip(handles, shaded['feat'])]
# Get saturation:
saturation_inds = []
for i in range(thresh_rel.size):
ind = get_saturation(noise_data['measure_feat'][:, i], **plateau_settings)[1]
saturation_inds.append(ind)
# Add proxy legend:
if ax == alpha_ax:
h1 = ax.plot([], [], c='k', lw=lw['big'], label='$\\alpha\\cdot s(t) + \\eta(t)$')[0]
h2 = ax.plot([], [], c='k', lw=lw['big'], ls='dotted', label='$\\alpha\\cdot s(t)$')[0]
ax.legend(handles=[h1, h2], **leg_kwargs)
# Plot analysis results:
for ax, x in zip([alpha_ax, sigma_ax], [scales, noise_data['measure_inv']]):
# Plot pure-song analysis results:
handles = ax.plot(x, pure_data['measure_feat'], lw=lw['big'], ls='dotted')
[h.set_color(c) for h, c in zip(handles, shaded['feat'])]
if save_path is not None:
fig.savefig(save_path)
plt.show()
# Plot noise-song analysis results:
handles = ax.plot(x, noise_data['measure_feat'], lw=lw['big'])
[h.set_color(c) for h, c in zip(handles, shaded['feat'])]
# Indicate threshold-specific saturation:
for i, ind in enumerate(saturation_inds):
color = shaded['feat'][i]
ax.plot(x[ind], 0, c='w', alpha=1, zorder=5.5, **plateau_dot_kwargs,
transform=ax.get_xaxis_transform())
ax.plot(x[ind], 0, mfc=color, mec='k', alpha=0.75, zorder=6,
**plateau_dot_kwargs, transform=ax.get_xaxis_transform())
ax.vlines(x[ind], ax.get_ylim()[0], noise_data['measure_feat'][ind, i],
color=color, **plateau_line_kwargs)
# Add proxy legend:
if ax == alpha_ax:
h1 = ax.plot([], [], c='k', lw=lw['big'], label='$\\alpha\\cdot s(t) + \\eta(t)$')[0]
h2 = ax.plot([], [], c='k', lw=lw['big'], ls='dotted', label='$\\alpha\\cdot s(t)$')[0]
ax.legend(handles=[h1, h2], **leg_kwargs)
if save_path is not None:
fig.savefig(save_path)
plt.show()
print('Done.')
embed()