Cross-checked and polished remainders of fig_invariance_thresh_lp_species.pdf.

Added misc_functions.py for anything not plot-related.
This commit is contained in:
j-hartling
2026-03-31 09:36:55 +02:00
parent 411d50ffcf
commit 298969a067
12 changed files with 251 additions and 165 deletions

Binary file not shown.

View File

@@ -248,25 +248,25 @@
\newlabel{eq:toy_log}{{12}{11}{}{}{}}
\newlabel{eq:toy_highpass}{{13}{11}{}{}{}}
\newlabel{eq:toy_snr}{{14}{12}{}{}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces \textbf {Intensity invariance by logarithmic compression and adaptation is restricted by the noise floor.} Synthetic input $x_{\text {filt}}(t)$ consists of song component $s(t)$ scaled by $\alpha $ with (\textbf {c}{} and \textbf {d}) or without (\textbf {a}{} and \textbf {b}) additive noise component $\eta (t)$. Input $x_{\text {filt}}(t)$ is transformed into envelope $x_{\text {env}}(t)$, logarithmically compressed envelope $x_{\text {dB}}(t)$, and intensity-adapted envelope $x_{\text {adapt}}(t)$. \textbf {Left}:~$x_{\text {env}}(t)$, $x_{\text {dB}}(t)$, and $x_{\text {adapt}}(t)$ for different scales $\alpha $. \textbf {Right}:~Ratios of the standard deviation of $x_{\text {env}}(t)$, $x_{\text {dB}}(t)$, and $x_{\text {adapt}}(t)$ relative to the respective reference standard deviation $\sigma _{\eta }$ for input $x_{\text {filt}}(t)=\eta (t)$. \textbf {a}{} and \textbf {b}:~Ideally, if $x_{\text {filt}}(t)=\alpha \cdot s(t)$, then $x_{\text {adapt}}(t)$ is intensity-invariant across all $\alpha $. \textbf {c}{} and \textbf {d}:~In practice, if $x_{\text {filt}}(t)=\alpha \cdot s(t)+\eta (t)$, the intensity invariance of $x_{\text {adapt}}(t)$ is limited to sufficiently large $\alpha $. Shaded area indicates saturation of $x_{\text {adapt}}(t)$ at $95\,\%$ curve span. }}{12}{}\protected@file@percent }
\newlabel{fig:inv_log-hp}{{4}{12}{}{}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Thresholding nonlinearity \& temporal averaging}{12}{}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces \textbf {Intensity invariance by thresholding and temporal averaging depends on both the threshold value and the noise floor.} Synthetic input $x_{\text {adapt}}(t)$ consists of song component $s(t)$ scaled by $\alpha $ with additive noise component $\eta (t)$. Input $x_{\text {adapt}}(t)$ is transformed into kernel response $c_i(t)$, binary response $b_i(t)$, and feature $f_i(t)$. Threshold value $\Theta _i$ is set to multiples of the reference standard deviation $\sigma _{\eta }$ of $c_i(t)$ for input $x_{\text {adapt}}(t)=\eta (t)$. Darker colors correspond to higher $\Theta _i$. \textbf {Left}:~$x_{\text {adapt}}(t)$, $c_i(t)$, $b_i(t)$, and $f_i(t)$ for different scales $\alpha $ and threshold values $\Theta _i$. Left-most column is is the pure-noise reference. \textbf {Right}:~Average value of $f_i(t)$ during the song for the different $\Theta _i$. \textbf {a}:~Input $x_{\text {adapt}}(t)$. \textbf {b}-\textbf {d}:~$c_i(t)$, $b_i(t)$, and $f_i(t)$ for the different $\Theta _i$ based on the same $x_{\text {adapt}}(t)$ from \textbf {a}{}. \textbf {e}:~Average value of $f_i(t)$ during the song for the different $\Theta _i$ in \textbf {b}{}-\textbf {d}. }}{13}{}\protected@file@percent }
\newlabel{fig:inv_thresh-lp_single}{{5}{13}{}{}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {6}{\ignorespaces \textbf {Feature representation of different species-specific songs saturates at different points in feature space.} }}{13}{}\protected@file@percent }
\newlabel{fig:inv_thresh-lp_species}{{6}{13}{}{}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {7}{\ignorespaces \textbf {Step-wise emergence of intensity invariant song representation along the model pathway.} }}{14}{}\protected@file@percent }
\newlabel{fig:inv_thresh-lp_full}{{7}{14}{}{}{}}
\newlabel{eq:pdf_split}{{15}{14}{}{}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces \textbf {Intensity invariance by logarithmic compression and adaptation is restricted by the noise floor.} Synthetic input $x_{\text {filt}}(t)$ consists of song component $s(t)$ scaled by $\alpha $ with (\textbf {c}{} and \textbf {d}) or without (\textbf {a}{} and \textbf {b}) additive noise component $\eta (t)$. Input $x_{\text {filt}}(t)$ is transformed into envelope $x_{\text {env}}(t)$, logarithmically compressed envelope $x_{\text {dB}}(t)$, and intensity-adapted envelope $x_{\text {adapt}}(t)$. \textbf {Left}:~$x_{\text {env}}(t)$, $x_{\text {dB}}(t)$, and $x_{\text {adapt}}(t)$ for different scales $\alpha $. \textbf {Right}:~Ratios of the standard deviation of $x_{\text {env}}(t)$, $x_{\text {dB}}(t)$, and $x_{\text {adapt}}(t)$ relative to the respective reference standard deviation $\sigma _{\eta }$ for input $x_{\text {filt}}(t)=\eta (t)$. \textbf {a}{} and \textbf {b}:~Ideally, if $x_{\text {filt}}(t)=\alpha \cdot s(t)$, then $x_{\text {adapt}}(t)$ is intensity-invariant across all $\alpha $. \textbf {c}{} and \textbf {d}:~In practice, if $x_{\text {filt}}(t)=\alpha \cdot s(t)+\eta (t)$, the intensity invariance of $x_{\text {adapt}}(t)$ is limited to sufficiently large $\alpha $. Shaded area indicates saturation of $x_{\text {adapt}}(t)$ at $95\,\%$ curve span. }}{13}{}\protected@file@percent }
\newlabel{fig:inv_log-hp}{{4}{13}{}{}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Thresholding nonlinearity \& temporal averaging}{14}{}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces \textbf {Intensity invariance by thresholding and temporal averaging depends on both the threshold value and the noise floor.} Synthetic input $x_{\text {adapt}}(t)$ consists of song component $s(t)$ scaled by $\alpha $ with additive noise component $\eta (t)$. Input $x_{\text {adapt}}(t)$ is transformed into kernel response $c_i(t)$, binary response $b_i(t)$, and feature $f_i(t)$. Threshold value $\Theta _i$ is set to multiples of the reference standard deviation $\sigma _{\eta }$ of $c_i(t)$ for input $x_{\text {adapt}}(t)=\eta (t)$. Darker colors correspond to higher $\Theta _i$. \textbf {Left}:~$x_{\text {adapt}}(t)$, $c_i(t)$, $b_i(t)$, and $f_i(t)$ for different scales $\alpha $ and threshold values $\Theta _i$. Left-most column is is the pure-noise reference. \textbf {Right}:~Average value of $f_i(t)$ during the song for the different $\Theta _i$. \textbf {a}:~Input $x_{\text {adapt}}(t)$. \textbf {b}-\textbf {d}:~$c_i(t)$, $b_i(t)$, and $f_i(t)$ for the different $\Theta _i$ based on the same $x_{\text {adapt}}(t)$ from \textbf {a}{}. \textbf {e}:~Average value of $f_i(t)$ during the song for the different $\Theta _i$ in \textbf {b}{}-\textbf {d}. }}{14}{}\protected@file@percent }
\newlabel{fig:inv_thresh-lp_single}{{5}{14}{}{}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {6}{\ignorespaces \textbf {Feature representation of different species-specific songs saturates at different points in feature space.} }}{15}{}\protected@file@percent }
\newlabel{fig:inv_thresh-lp_species}{{6}{15}{}{}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {7}{\ignorespaces \textbf {Step-wise emergence of intensity invariant song representation along the model pathway.} }}{16}{}\protected@file@percent }
\newlabel{fig:inv_thresh-lp_full}{{7}{16}{}{}{}}
\newlabel{eq:pdf_split}{{15}{17}{}{}{}}
\newlabel{eq:feat_avg}{{16}{17}{}{}{}}
\newlabel{eq:feat_prop}{{17}{17}{}{}{}}
\abx@aux@cite{0}{stumpner1991auditory}
\abx@aux@segm{0}{0}{stumpner1991auditory}
\newlabel{eq:feat_avg}{{16}{15}{}{}{}}
\newlabel{eq:feat_prop}{{17}{15}{}{}{}}
\@writefile{toc}{\contentsline {section}{\numberline {4}Discriminating species-specific song\\patterns in feature space}{16}{}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {5}Conclusions \& outlook}{16}{}\protected@file@percent }
\abx@aux@page{73}{16}
\@writefile{lof}{\contentsline {figure}{\numberline {8}{\ignorespaces \textbf {} }}{17}{}\protected@file@percent }
\newlabel{}{{8}{17}{}{}{}}
\@writefile{toc}{\contentsline {section}{\numberline {4}Discriminating species-specific song\\patterns in feature space}{18}{}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {5}Conclusions \& outlook}{18}{}\protected@file@percent }
\abx@aux@page{73}{18}
\@writefile{lof}{\contentsline {figure}{\numberline {8}{\ignorespaces \textbf {} }}{20}{}\protected@file@percent }
\newlabel{}{{8}{20}{}{}{}}
\gdef\svg@ink@ver@settings{{\m@ne }{inkscape}{\m@ne }}
\abx@aux@read@bbl@mdfivesum{1380DC8C93D2855FDB132CC5A40AD52F}
\gdef \@abspage@last{17}
\gdef \@abspage@last{20}

View File

@@ -1,14 +1,14 @@
# Fdb version 4
["biber main"] 1774450439.36422 "main.bcf" "main.bbl" "main" 1774450447.31629 0
["biber main"] 1774450439.36422 "main.bcf" "main.bbl" "main" 1774939289.27389 0
"cite.bib" 1770904753.08918 27483 4290db0c91f7b5055e25472ef913f6b4 ""
"main.bcf" 1774450447.19902 112931 2a478116d80ebb1ada7083a24facd6e3 "pdflatex"
"main.bcf" 1774939289.16212 112931 2a478116d80ebb1ada7083a24facd6e3 "pdflatex"
(generated)
"main.bbl"
"main.blg"
(rewritten before read)
["pdflatex"] 1774450445.69982 "/home/hartling/phd/paper/paper_2025/main.tex" "main.pdf" "main" 1774450447.31653 0
["pdflatex"] 1774939287.87141 "/home/hartling/phd/paper/paper_2025/main.tex" "main.pdf" "main" 1774939289.27409 0
"/etc/texmf/web2c/texmf.cnf" 1761560044.43676 475 c0e671620eb5563b2130f56340a5fde8 ""
"/home/hartling/phd/paper/paper_2025/main.tex" 1774450445.38503 48022 de46789e7f0ca716a47759b334bfa10b ""
"/home/hartling/phd/paper/paper_2025/main.tex" 1774450464.03788 48022 de46789e7f0ca716a47759b334bfa10b ""
"/usr/share/texlive/texmf-dist/fonts/map/fontname/texfonts.map" 1577235249 3524 cb3e574dea2d1052e39280babc910dc8 ""
"/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm" 1246382020 1004 54797486969f23fa377b128694d548df ""
"/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm" 1246382020 988 bdf658c3bfc2d96d3c8b02cfc1c94c20 ""
@@ -154,15 +154,15 @@
"figures/fig_auditory_pathway.pdf" 1771593904.14638 1153923 3df8539421fd21dc866cc8d320bd9b1d ""
"figures/fig_feat_stages.pdf" 1774002994.98767 11091006 565fe951f1255c121429a060082398f5 ""
"figures/fig_invariance_full.pdf" 1774271483.89842 149796490 a2dd04969d8a98c63c3653d20848c0b6 ""
"figures/fig_invariance_log_hp.pdf" 1774270814.43169 544402 7a2def404adc93a3e18fa8b309d452be ""
"figures/fig_invariance_log_hp.pdf" 1774862828.87982 837296 93dd5e5b25285f2b3d6c8e3c0d2fd5f1 ""
"figures/fig_invariance_thresh_lp_single.pdf" 1774448531.93474 921028 cae18b62e262b42f630e219fcaa0ca09 ""
"figures/fig_invariance_thresh_lp_species.pdf" 1773741140.93995 47573 9dd8a2281ce467803dd2a7b74ff3373e ""
"figures/fig_invariance_thresh_lp_species.pdf" 1774881323.87307 397460 b03004b5f296b884384b46c1419a5edf ""
"figures/fig_noise_env_sd_conversion.pdf" 1774256952.42051 45466 671a2b8fbf72b4eba6b970b4421f2521 ""
"figures/fig_pre_stages.pdf" 1774002992.74268 449426 5762be15627fe5d8b6d108b7ea18db44 ""
"main.aux" 1774450447.19302 15278 2c66d13a9cb30f6854e7c7e85ce0fb43 "pdflatex"
"main.aux" 1774939289.15612 15278 8ddadc678eacbeaae96061ab2907f0b9 "pdflatex"
"main.bbl" 1774450439.97007 91039 1380dc8c93d2855fdb132cc5a40ad52f "biber main"
"main.run.xml" 1774450447.20002 2335 a049bc26a7f032e842ce55de5bc38328 "pdflatex"
"main.tex" 1774450445.38503 48022 de46789e7f0ca716a47759b334bfa10b ""
"main.run.xml" 1774939289.16212 2335 a049bc26a7f032e842ce55de5bc38328 "pdflatex"
"main.tex" 1774450464.03788 48022 de46789e7f0ca716a47759b334bfa10b ""
(generated)
"main.aux"
"main.bcf"

View File

@@ -1,4 +1,4 @@
This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023/Debian) (preloaded format=pdflatex 2025.10.28) 25 MAR 2026 15:54
This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023/Debian) (preloaded format=pdflatex 2025.10.28) 31 MAR 2026 08:41
entering extended mode
restricted \write18 enabled.
file:line:error style messages enabled.
@@ -764,37 +764,41 @@ File: figures/fig_feat_stages.pdf Graphic file (type pdf)
Package pdftex.def Info: figures/fig_feat_stages.pdf used on input line 542.
(pdftex.def) Requested size: 483.69687pt x 241.84782pt.
[10 <./figures/fig_feat_stages.pdf>] [11]
<figures/fig_invariance_log_hp.pdf, id=1141, 895.57933pt x 469.40372pt>
<figures/fig_invariance_log_hp.pdf, id=1141, 890.96089pt x 918.57785pt>
File: figures/fig_invariance_log_hp.pdf Graphic file (type pdf)
<use figures/fig_invariance_log_hp.pdf>
Package pdftex.def Info: figures/fig_invariance_log_hp.pdf used on input line 632.
(pdftex.def) Requested size: 483.69687pt x 253.52437pt.
<figures/fig_invariance_thresh_lp_single.pdf, id=1142, 910.48819pt x 455.2441pt>
(pdftex.def) Requested size: 483.69687pt x 498.70178pt.
[12]
LaTeX Warning: Text page 13 contains only floats.
[13 <./figures/fig_invariance_log_hp.pdf>]
<figures/fig_invariance_thresh_lp_single.pdf, id=1229, 910.48819pt x 455.2441pt>
File: figures/fig_invariance_thresh_lp_single.pdf Graphic file (type pdf)
<use figures/fig_invariance_thresh_lp_single.pdf>
Package pdftex.def Info: figures/fig_invariance_thresh_lp_single.pdf used on input line 663.
(pdftex.def) Requested size: 483.69687pt x 241.84782pt.
[12 <./figures/fig_invariance_log_hp.pdf>]
<figures/fig_invariance_thresh_lp_species.pdf, id=1199, 910.48819pt x 455.2441pt>
<figures/fig_invariance_thresh_lp_species.pdf, id=1230, 910.48819pt x 910.48819pt>
File: figures/fig_invariance_thresh_lp_species.pdf Graphic file (type pdf)
<use figures/fig_invariance_thresh_lp_species.pdf>
Package pdftex.def Info: figures/fig_invariance_thresh_lp_species.pdf used on input line 693.
(pdftex.def) Requested size: 483.69687pt x 241.84782pt.
[13 <./figures/fig_invariance_thresh_lp_single.pdf> <./figures/fig_invariance_thresh_lp_species.pdf>]
<figures/fig_invariance_full.pdf, id=1325, 910.48819pt x 455.2441pt>
(pdftex.def) Requested size: 483.69687pt x 483.69566pt.
[14 <./figures/fig_invariance_thresh_lp_single.pdf>]
<figures/fig_invariance_full.pdf, id=1302, 910.48819pt x 455.2441pt>
File: figures/fig_invariance_full.pdf Graphic file (type pdf)
<use figures/fig_invariance_full.pdf>
Package pdftex.def Info: figures/fig_invariance_full.pdf used on input line 703.
(pdftex.def) Requested size: 483.69687pt x 241.84782pt.
[14
[15 <./figures/fig_invariance_thresh_lp_species.pdf>] [16 <./figures/fig_invariance_full.pdf>] [17
<./figures/fig_invariance_full.pdf>] [15] [16]
<figures/fig_noise_env_sd_conversion.pdf, id=1388, 910.48819pt x 455.2441pt>
] [18]
<figures/fig_noise_env_sd_conversion.pdf, id=1501, 910.48819pt x 455.2441pt>
File: figures/fig_noise_env_sd_conversion.pdf Graphic file (type pdf)
<use figures/fig_noise_env_sd_conversion.pdf>
Package pdftex.def Info: figures/fig_noise_env_sd_conversion.pdf used on input line 862.
(pdftex.def) Requested size: 483.69687pt x 241.84782pt.
[17 <./figures/fig_noise_env_sd_conversion.pdf>] (./main.aux)
[19] [20 <./figures/fig_noise_env_sd_conversion.pdf>] (./main.aux)
***********
LaTeX2e <2023-11-01> patch level 1
L3 programming layer <2024-01-22>
@@ -812,10 +816,10 @@ Here is how much of TeX's memory you used:
1143 hyphenation exceptions out of 8191
94i,19n,93p,1496b,1732s stack positions out of 10000i,1000n,20000p,200000b,200000s
</usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmbxti10.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmex10.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi12.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi6.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi8.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr12.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr17.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr6.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr8.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy8.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmti12.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/symbols/msbm10.pfb>
Output written on main.pdf (17 pages, 164189765 bytes).
Output written on main.pdf (20 pages, 164834440 bytes).
PDF statistics:
1521 PDF objects out of 1728 (max. 8388607)
843 compressed objects within 9 object streams
1638 PDF objects out of 1728 (max. 8388607)
867 compressed objects within 9 object streams
0 named destinations out of 1000 (max. 500000)
53 words of extra memory for PDF output out of 10000 (max. 10000000)

BIN
main.pdf

Binary file not shown.

Binary file not shown.

View File

@@ -4,10 +4,11 @@ import matplotlib.pyplot as plt
from itertools import product
from thunderhopper.filetools import search_files
from thunderhopper.modeltools import load_data
from misc_functions import shorten_species, get_saturation
from color_functions import load_colors
from plot_functions import hide_axis, ylimits, xlabel, ylabel, hide_ticks,\
from plot_functions import hide_axis, ylimits, super_xlabel, ylabel, hide_ticks,\
plot_line, strip_zeros, time_bar, zoom_inset,\
letter_subplot, title_subplot
letter_subplot, letter_subplots, title_subplot
from IPython import embed
def add_snip_axes(fig, grid_kwargs):
@@ -30,7 +31,14 @@ def plot_snippets(axes, time, snippets, ymin=None, ymax=None, **kwargs):
# GENERAL SETTINGS:
target = 'Omocestus_rufipes'
data_paths = search_files(target, excl='noise', dir='../data/inv/log_hp/')
species_paths = search_files('*', incl='noise', dir='../data/inv/log_hp/')
target_species = [
'Omocestus_rufipes',
'Chorthippus_biguttulus',
'Chorthippus_mollis',
'Chrysochraon_dispar',
'Gomphocerippus_rufus',
'Pseudochorthippus_parallelus',
]
stages = ['env', 'log', 'inv']
load_kwargs = dict(
files=stages,
@@ -39,28 +47,29 @@ load_kwargs = dict(
save_path = '../figures/fig_invariance_log_hp.pdf'
compute_ratios = True
show_diag = True
show_noise = True
show_plateaus = True
# GRAPH SETTINGS:
fig_kwargs = dict(
figsize=(32/2.54, 32/2.54),
)
snip_rows = 1
big_rows = 1
# snip_rows = 1
# big_rows = 1
super_grid_kwargs = dict(
nrows=2 * snip_rows + big_rows,
nrows=3,
ncols=1,
wspace=0,
hspace=0,
left=0,
right=1,
bottom=0,
top=1
top=1,
height_ratios=[1, 1, 1]
)
subfig_specs = dict(
pure=(slice(0, snip_rows), slice(None)),
noise=(slice(snip_rows, 2 * snip_rows), slice(None)),
big=(slice(-big_rows, None), slice(None)),
pure=(0, slice(None)),
noise=(1, slice(None)),
big=(2, slice(None)),
)
block_height = 0.8
edge_padding = 0.08
@@ -112,6 +121,8 @@ fs = dict(
bar=16,
)
colors = load_colors('../data/stage_colors.npz')
species_colors = load_colors('../data/species_colors.npz')
noise_colors = [(0.5, 0.5, 0.5), (0.7, 0.7, 0.7)]
lw_snippets = 1
lw_big = 3
xlabels = dict(
@@ -206,15 +217,34 @@ bar_kwargs = dict(
va='center',
)
)
leg_kwargs = dict(
ncols=2,
loc='upper right',
bbox_to_anchor=(0, 0.6, 1, 0.4),
frameon=False,
prop=dict(
size=12,
style='italic',
),
borderpad=0,
borderaxespad=0,
handlelength=1,
columnspacing=1,
)
diag_kwargs = dict(
c=(0.75, 0.75, 0.75),
lw=2,
ls='--',
zorder=1.9,
)
noise_rel_thresh = 0.95
noise_kwargs = dict(
fc=(0.9, 0.9, 0.9),
plateau_settings = dict(
low=0.05,
high=0.95,
first=True,
last=True,
condense=None,
)
plateau_kwargs = dict(
ec='none',
lw=0,
zorder=1.5,
@@ -225,13 +255,13 @@ if compute_ratios:
ref_data = load_data('../data/processed/white_noise_sd-1.npz', files=stages)[0]
ref_measures = {k: v.std() for k, v in ref_data.items() if not k.endswith('rate')}
species_measures = []
for species_path in species_paths:
species_measure = load_data(species_path, **load_kwargs)[0]['measure_inv']
species_measures = {}
for species in target_species:
path = search_files(species, incl='noise', dir='../data/inv/log_hp/')[0]
measure = load_data(path, **load_kwargs)[0]['measure_inv']
if compute_ratios:
species_measure /= ref_measures['inv']
species_measures.append(species_measure)
species_measures = np.array(species_measures).T
measure /= ref_measures['inv']
species_measures[species] = measure
# EXECUTION:
for data_path in data_paths:
@@ -291,14 +321,10 @@ for data_path in data_paths:
ax.set_xscale('symlog', linthresh=scales[1], linscale=0.5)
ax.set_yscale('symlog', linthresh=scales[1], linscale=0.5)
ax.set_aspect(**anchor_kwargs)
ylabel(ax, ylabels['big'], transform=big_subfig.transSubfigure, **ylab_big_kwargs)
if i == 0:
hide_ticks(ax, 'bottom')
letter_subplot(ax, 'c', **letter_big_kwargs)
else:
xlabel(ax, xlabels['big'], transform=big_subfig.transSubfigure, **xlab_big_kwargs)
letter_subplot(ax, 'd', **letter_big_kwargs)
big_axes[i] = ax
ylabel(big_axes[0], ylabels['big'], transform=big_subfig.transSubfigure, **ylab_big_kwargs)
super_xlabel(xlabels['big'], big_subfig, big_axes[0], big_axes[-1], **xlab_big_kwargs)
letter_subplots(big_axes, 'cde', **letter_big_kwargs)
# Plot pure-song envelope snippets:
handle = plot_snippets(pure_axes[0, :], t_full, pure_data['snip_env'],
@@ -352,25 +378,26 @@ for data_path in data_paths:
big_axes[1].plot(noise_scales, noise_data['measure_log'], c=colors['log'], lw=lw_big)
big_axes[1].plot(noise_scales, noise_data['measure_inv'], c=colors['inv'], lw=lw_big)
# Plot species measures:
big_axes[2].plot(noise_scales, species_measures, 'k', lw=lw_big)
if show_diag:
# Indicate diagonal:
big_axes[0].plot(pure_scales, pure_scales, **diag_kwargs)
big_axes[1].plot(noise_scales, noise_scales, **diag_kwargs)
if show_noise:
# Indicate noise floor:
if compute_ratios:
span_measure = noise_data['measure_inv'][-1] - ref_measures['inv']
thresh_measure = ref_measures['inv'] + noise_rel_thresh * span_measure
else:
span_measure = noise_data['measure_inv'][-1] - noise_data['measure_inv'][0]
thresh_measure = noise_data['measure_inv'][0] + noise_rel_thresh * span_measure
thresh_ind = np.nonzero(noise_data['measure_inv'] < thresh_measure)[0][-1]
thresh_scale = noise_scales[thresh_ind]
big_axes[1].axvspan(noise_scales[0], thresh_scale, **noise_kwargs)
if show_plateaus:
# Indicate low and high plateaus of noise invariance curve:
low_ind, high_ind = get_saturation(noise_data['measure_inv'], **plateau_settings)
big_axes[1].axvspan(noise_scales[0], noise_scales[low_ind],
fc=noise_colors[0], **plateau_kwargs)
big_axes[1].axvspan(noise_scales[low_ind], noise_scales[high_ind],
fc=noise_colors[1], **plateau_kwargs)
# Plot species-specific noise-song measures:
for species, measure in species_measures.items():
label = shorten_species(species)
big_axes[2].plot(noise_scales, measure, label=label,
c=species_colors[species], lw=lw_big)
big_axes[2].legend(**leg_kwargs)
if save_path is not None:
fig.savefig(save_path, bbox_inches='tight')

View File

@@ -7,11 +7,11 @@ from itertools import product
from thunderhopper.filetools import search_files
from thunderhopper.modeltools import load_data
from thunderhopper.filtertools import find_kern_specs
from misc_functions import shorten_species, get_saturation
from color_functions import load_colors, shade_colors, create_listed_cmap
from plot_functions import hide_axis, title_subplot, ylimits, xlabel, ylabel, super_ylabel,\
plot_line, plot_barcode, strip_zeros, time_bar,\
letter_subplot, letter_subplots, hide_ticks,\
super_xlabel, super_ylabel, assign_colors
from plot_functions import hide_axis, title_subplot, ylimits, xlabel, ylabel,\
plot_line, time_bar,letter_subplot, letter_subplots,\
hide_ticks, super_xlabel, reorder_by_norm
from IPython import embed
def force_sequence(*vars, skip_None=False, equal_size=False):
@@ -126,10 +126,6 @@ def split_subplot(ax, side='right', size=10, pad=10):
inputs = zip(*force_sequence(side, size, pad, equal_size=True))
return [div.append_axes(s, f'{n}%', f'{p}%') for s, n, p in inputs]
def shorten_species(name):
genus, species = name.split('_')
return genus[0] + '. ' + species
def add_cross_axes(fig, n, long='col', fill='row', **grid_kwargs):
n_axes = n * (n - 1) // 2
nrows = grid_kwargs.get('nrows', None)
@@ -179,7 +175,7 @@ load_kwargs = dict(
)
save_path = '../figures/fig_invariance_thresh_lp_species.pdf'
exclude_zero = True
show_noise = True
show_floor = True
# SUBSET SETTINGS:
thresh_rel = np.array([0.5, 1, 3])[0]
@@ -214,7 +210,7 @@ subfig_specs = dict(
feat_grid_kwargs = dict(
nrows=2,
ncols=n_species,
wspace=0.25,
wspace=0.35,
hspace=0.1,
left=0.06,
right=0.985,
@@ -234,17 +230,16 @@ song_grid_kwargs = dict(
space_grid_kwargs = dict(
nrows=None,
ncols=None,
wspace=0.1,
hspace=0.3,
left=0.05,
right=1,
bottom=0.1,
wspace=0,
hspace=0.4,
left=0.15,
right=0.9,
bottom=0.13,
top=0.95
)
anchor_kwargs = dict(
aspect='equal',
adjustable='box',
anchor=(0.5, 0.5)
)
inset_kwargs = dict(
y0=0.7,
@@ -264,10 +259,12 @@ fs = dict(
species_colors = load_colors('../data/species_colors.npz')
kernel_shades = [0, 0.75]
scale_shades = [1, 0]
noise_colors = [(0.5, 0.5, 0.5), (0.7, 0.7, 0.7)]
lw = dict(
song=0.5,
feat=3,
kern=3
kern=2.5,
plateau=3,
)
zorder = dict(
Omocestus_rufipes=2,
@@ -285,7 +282,7 @@ xlabels = dict(
space=[f'$\\mu_{{f_{i}}}$' for i in range(1, n_kernels + 1)],
)
ylabels = dict(
feat='$\\mu_f$',
feat='$\\mu_{f_i}$',
space=[f'$\\mu_{{f_{i}}}$' for i in range(1, n_kernels + 1)],
bar='scale $\\alpha$',
)
@@ -296,10 +293,10 @@ xlab_feat_kwargs = dict(
va='bottom',
)
xlab_space_kwargs = dict(
y=-0.3,
y=-0.2,
fontsize=fs['lab_tex'],
ha='center',
va='bottom',
va='top',
)
ylab_feat_kwargs = dict(
x=0,
@@ -308,13 +305,14 @@ ylab_feat_kwargs = dict(
va='top',
)
ylab_space_kwargs = dict(
x=-0.2,
x=-0.3,
rotation=0,
fontsize=fs['lab_tex'],
ha='center',
va='bottom',
ha='right',
va='center',
)
ylab_cbar_kwargs = dict(
x=1,
x=-2,
fontsize=fs['lab_norm'],
ha='center',
va='bottom',
@@ -368,30 +366,43 @@ song_bar_kwargs = dict(
color='k',
lw=0,
clip_on=False,
# text_pos=(-0.1, 0.5),
# text_str=f'${int(1000 * song_bar_time)}\\,\\text{{ms}}$',
# text_kwargs=dict(
# fontsize=fs['bar'],
# ha='right',
# va='center',
# )
text_pos=(1.25, 0.5),
text_str=f'${int(song_bar_time)}\\,\\text{{s}}$',
text_kwargs=dict(
fontsize=fs['bar'],
ha='left',
va='center',
)
)
kern_bar_time = 0.05
kern_bar_kwargs = dict(
dur=kern_bar_time,
y0=inset_kwargs['y0'] - 0.03,
y1=inset_kwargs['y0'],
y0=0.1,
y1=0.2,
color='k',
lw=0
lw=0,
clip_on=False,
text_pos=(0.6, -1),
text_str=f'${int(kern_bar_time * 1000)}\\,\\text{{ms}}$',
text_kwargs=dict(
fontsize=fs['bar'],
ha='center',
va='top',
)
)
noise_kwargs = dict(
floor_kwargs = dict(
fc=(0.9, 0.9, 0.9),
ec='none',
lw=0,
zorder=0.5,
)
low_rel_thresh = 0.05
high_rel_thresh = 0.95
plateau_settings = dict(
low=0.05,
high=0.95,
first=True,
last=True,
condense='norm',
)
# EXECUTION:
@@ -450,14 +461,17 @@ letter_subplot(noise_subfig, 'e', ref=noise_axes[0], **letter_space_kwargs)
# Format feature space axes:
for ind, axes in enumerate(zip(pure_axes, noise_axes)):
irow, icol = row_inds[ind], col_inds[ind]
for ax in axes:
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.xaxis.set_major_locator(plt.MultipleLocator(xloc['space']))
ax.yaxis.set_major_locator(plt.MultipleLocator(yloc['space']))
ax.set_aspect(**anchor_kwargs)
xlabel(ax, xlabels['space'][col_inds[ind]], **xlab_space_kwargs)
ylabel(ax, ylabels['space'][row_inds[ind]], **ylab_space_kwargs)
anchor = space_pos[ind] / space_pos.max(axis=0)
anchor[0] = 1 - anchor[0]
ax.set_aspect(anchor=tuple(anchor[::-1]), **anchor_kwargs)
xlabel(ax, xlabels['space'][icol], **xlab_space_kwargs)
ylabel(ax, ylabels['space'][irow], **ylab_space_kwargs)
# Determine area to place colorbars:
rightmost = pure_axes[np.argmax(space_pos[:, 1])].get_position()
@@ -479,7 +493,11 @@ kern_factors = np.linspace(*kernel_shades, n_kernels)
kern_colors_bw = shade_colors((0., 0., 0.), kern_factors)
# Plot results per species:
noise_feat = np.zeros((n_species, n_kernels), dtype=float)
min_noise_feat = np.zeros((n_species, n_kernels), dtype=float)
max_pure_feat = np.zeros((n_species, n_kernels), dtype=float)
max_noise_feat = np.zeros((n_species, n_kernels), dtype=float)
pure_space_handles = {ax: [] for ax in pure_axes}
noise_space_handles = {ax: [] for ax in noise_axes}
for i, species in enumerate(target_species):
print(f'Processing {species}')
@@ -496,6 +514,7 @@ for i, species in enumerate(target_species):
plot_line(song_ax, time, song, ypad=0.05, c='k', lw=lw['song'])
title_subplot(song_ax, shorten_species(species), ref=song_subfig, **title_kwargs)
time_bar(song_ax, **song_bar_kwargs)
song_bar_kwargs['text_pos'] = None
# Fetch species-specific invariance files:
pure_path = search_files(species, incl='pure', dir='../data/inv/thresh_lp/')[0]
@@ -545,7 +564,8 @@ for i, species in enumerate(target_species):
inset.plot(config['k_times'], kern, c=c, lw=lw['kern'])
inset.set_xlim(xlims)
inset.set_ylim(ylims)
time_bar(insets[0], parent=feat_axes[0, 0], **kern_bar_kwargs)
# time_bar(insets[0], parent=feat_axes[0, 0], **kern_bar_kwargs)
time_bar(insets[0], **kern_bar_kwargs)
# Plot invariance curves in feature space:
norm = LogNorm(vmin=scales[scales > 0][0], vmax=scales[-1])
@@ -554,60 +574,56 @@ for i, species in enumerate(target_species):
pure_handle = pure_ax.scatter(pure_measure[:, icol], pure_measure[:, irow],
c=scales, cmap=scale_cmap, norm=norm,
zorder=zorder[species], **space_kwargs)
pure_space_handles[pure_ax].append(pure_handle)
noise_handle = noise_ax.scatter(noise_measure[:, icol], noise_measure[:, irow],
c=scales, cmap=scale_cmap, norm=norm,
zorder=zorder[species], **space_kwargs)
noise_space_handles[noise_ax].append(noise_handle)
# Indicate scale color code in pure subfigure:
pure_subfig.colorbar(pure_handle, cax=pure_bars[i])
pure_bars[i].set_yscale('symlog', **symlog_kwargs)
if i < n_species - 1:
hide_ticks(pure_bars[i], 'right', ticks=False)
else:
ylabel(pure_bars[i], ylabels['bar'], transform=pure_subfig.transSubfigure, **ylab_cbar_kwargs)
hide_ticks(pure_bars[i], 'right', ticks=False)
if i == 0:
pure_bars[0].tick_params(axis='y', which='both', left=True, labelleft=True)
ylabel(pure_bars[0], ylabels['bar'], **ylab_cbar_kwargs)
# Indicate scale color code in noise subfigure:
noise_subfig.colorbar(noise_handle, cax=noise_bars[i])
noise_bars[i].set_yscale('symlog', **symlog_kwargs)
if i < n_species - 1:
hide_ticks(noise_bars[i], 'right', ticks=False)
else:
ylabel(noise_bars[i], ylabels['bar'], transform=noise_subfig.transSubfigure, **ylab_cbar_kwargs)
hide_ticks(noise_bars[i], 'right', ticks=False)
if i == 0:
noise_bars[0].tick_params(axis='y', which='both', left=True, labelleft=True)
ylabel(noise_bars[0], ylabels['bar'], **ylab_cbar_kwargs)
# Log feature noise floor:
noise_feat[i, :] = noise_measure.min(axis=0)
# Indicate plateaus of pure invariance curves:
low_ind, high_ind = get_saturation(pure_measure, **plateau_settings)
pure_bars[i].axhline(scales[low_ind], c=noise_colors[0], lw=lw['plateau'])
pure_bars[i].axhline(scales[high_ind], c=noise_colors[1], lw=lw['plateau'])
# Indicate low and high plateaus:
min_feat = pure_measure.min(axis=0)
span_feat = pure_measure.max(axis=0) - min_feat
# Indicate plateaus of noise invariance curves:
low_ind, high_ind = get_saturation(noise_measure, **plateau_settings)
noise_bars[i].axhline(scales[low_ind], c=noise_colors[0], lw=lw['plateau'])
noise_bars[i].axhline(scales[high_ind], c=noise_colors[1], lw=lw['plateau'])
# Log start and end of invariance curve:
min_noise_feat[i, :] = noise_measure.min(axis=0)
max_pure_feat[i, :] = pure_measure.max(axis=0)
max_noise_feat[i, :] = noise_measure.max(axis=0)
low_thresh = min_feat + low_rel_thresh * span_feat
low_ind = np.nonzero((pure_measure >= low_thresh).all(axis=1))[0][0]
pure_bars[i].axhline(scales[low_ind], c='k', lw=3)
# Sort feature space traces by distance of endpoint to origin:
for ind, (pure_ax, noise_ax) in enumerate(zip(pure_axes, noise_axes)):
irow, icol = row_inds[ind], col_inds[ind]
reorder_by_norm(pure_space_handles[pure_ax], max_pure_feat[:, [icol, irow]])
reorder_by_norm(noise_space_handles[noise_ax], max_noise_feat[:, [icol, irow]])
high_thresh = min_feat + high_rel_thresh * span_feat
high_ind = np.nonzero((pure_measure >= high_thresh).any(axis=1))[0][0]
pure_bars[i].axhline(scales[high_ind], c='w', lw=3)
# Indicate low and high plateaus:
min_feat = noise_measure.min(axis=0)
span_feat = noise_measure.max(axis=0) - min_feat
low_thresh = min_feat + low_rel_thresh * span_feat
low_ind = np.nonzero((noise_measure >= low_thresh).all(axis=1))[0][0]
noise_bars[i].axhline(scales[low_ind], c='k', lw=3)
high_thresh = min_feat + high_rel_thresh * span_feat
high_ind = np.nonzero((noise_measure >= high_thresh).any(axis=1))[0][0]
noise_bars[i].axhline(scales[high_ind], c='w', lw=3)
if show_noise:
if show_floor:
# Indicate feature noise floor:
noise_feat = noise_feat.mean(axis=0)
noise_feat = min_noise_feat.mean(axis=0)
for ind, ax in enumerate(noise_axes):
irow, icol = row_inds[ind], col_inds[ind]
ax.add_patch(plt.Rectangle((0, 0), noise_feat[icol], noise_feat[irow], **noise_kwargs))
ax.add_patch(plt.Rectangle((0, 0), noise_feat[icol], noise_feat[irow], **floor_kwargs))
if save_path is not None:
fig.savefig(save_path)

View File

@@ -6,7 +6,7 @@ from thunderhopper.modeltools import load_data
from color_functions import load_colors
from plot_functions import hide_axis, letter_subplots,\
ylabel, super_xlabel, plot_line, plot_barcode,\
indicate_zoom, assign_colors, reorder_traces
indicate_zoom, assign_colors, reorder_by_sd
from IPython import embed
# GENERAL SETTINGS:
@@ -215,10 +215,10 @@ for data_path in data_paths:
signal = data['conv'][:, kern_inds]
handles = plot_line(ax_full, t_full, signal, lw=lw_full['conv'], yloc=yloc_full['conv'])
assign_colors(handles, kern_specs[:, 0], conv_colors)
reorder_traces(handles, signal)
reorder_by_sd(handles, signal)
handles = plot_line(ax_zoom, t_zoom, signal[zoom_mask, :], lw=lw_zoom['conv'], yloc=yloc_zoom['conv'])
assign_colors(handles, kern_specs[:, 0], conv_colors)
reorder_traces(handles, signal[zoom_mask, :])
reorder_by_sd(handles, signal[zoom_mask, :])
hide_axis(ax_full, 'bottom')
hide_axis(ax_zoom, 'bottom')

32
python/misc_functions.py Normal file
View File

@@ -0,0 +1,32 @@
import numpy as np
def shorten_species(name):
genus, species = name.split('_')
return genus[0] + '. ' + species
def get_saturation(sigmoid, low=0.05, high=0.95, first=True, last=True,
condense=None):
if condense == 'norm' and sigmoid.ndim == 2:
sigmoid = np.linalg.norm(sigmoid, axis=1)
min_value = sigmoid[0] if first else sigmoid.min(axis=0)
max_value = sigmoid[-1] if last else sigmoid.max(axis=0)
span = max_value - min_value
low_value = min_value + low * span
high_value = min_value + high * span
low_mask = sigmoid >= low_value
high_mask = sigmoid >= high_value
if sigmoid.ndim == 1:
low_ind = np.nonzero(low_mask)[0][0]
high_ind = np.nonzero(high_mask)[0][0]
elif condense == 'all':
low_ind = np.nonzero(low_mask.all(axis=1))[0][0]
high_ind = np.nonzero(high_mask.all(axis=1))[0][0]
else:
low_ind, high_ind = [], []
for i in range(sigmoid.shape[1]):
low_ind.append(np.nonzero(low_mask[:, i])[0][0])
high_ind.append(np.nonzero(high_mask[:, i])[0][0])
return low_ind, high_ind

View File

@@ -202,8 +202,15 @@ def assign_colors(handles, types, colors):
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))
def reorder_by_sd(handles, data, zlow=2, zhigh=2.5):
inds = np.argsort(data.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 reorder_by_norm(handles, data, zlow=2, zhigh=2.5):
inds = np.argsort(np.linalg.norm(data, axis=1))
zorders = np.linspace(zlow, zhigh, len(inds))[::-1]
for ind, z in zip(inds, zorders):
handles[ind].set_zorder(z)