diff --git a/figures/fig_feat_stages.pdf b/figures/fig_feat_stages.pdf index d2ef3e8..e1066e7 100644 Binary files a/figures/fig_feat_stages.pdf and b/figures/fig_feat_stages.pdf differ diff --git a/figures/fig_invariance_full.pdf b/figures/fig_invariance_full.pdf new file mode 100644 index 0000000..08a92b1 Binary files /dev/null and b/figures/fig_invariance_full.pdf differ diff --git a/figures/fig_invariance_log_hp.pdf b/figures/fig_invariance_log_hp.pdf index 2349735..b5705e4 100644 Binary files a/figures/fig_invariance_log_hp.pdf and b/figures/fig_invariance_log_hp.pdf differ diff --git a/figures/fig_invariance_thresh_lp_single.pdf b/figures/fig_invariance_thresh_lp_single.pdf index 55b6a51..c0e55cb 100644 Binary files a/figures/fig_invariance_thresh_lp_single.pdf and b/figures/fig_invariance_thresh_lp_single.pdf differ diff --git a/figures/fig_invariance_thresh_lp_single_noise.pdf b/figures/fig_invariance_thresh_lp_single_noise.pdf index 26576f6..c3d1348 100644 Binary files a/figures/fig_invariance_thresh_lp_single_noise.pdf and b/figures/fig_invariance_thresh_lp_single_noise.pdf differ diff --git a/figures/fig_invariance_thresh_lp_species.pdf b/figures/fig_invariance_thresh_lp_species.pdf index 52bb66d..a549b02 100644 Binary files a/figures/fig_invariance_thresh_lp_species.pdf and b/figures/fig_invariance_thresh_lp_species.pdf differ diff --git a/figures/fig_noise_env_sd_conversion.pdf b/figures/fig_noise_env_sd_conversion.pdf new file mode 100644 index 0000000..5f0c720 Binary files /dev/null and b/figures/fig_noise_env_sd_conversion.pdf differ diff --git a/figures/fig_pre_stages.pdf b/figures/fig_pre_stages.pdf index aa8582b..5f991c2 100644 Binary files a/figures/fig_pre_stages.pdf and b/figures/fig_pre_stages.pdf differ diff --git a/main.aux b/main.aux index 325c4d1..2e0dea6 100644 --- a/main.aux +++ b/main.aux @@ -222,8 +222,8 @@ \abx@aux@page{68}{7} \abx@aux@page{69}{7} \newlabel{eq:highpass}{{4}{7}{}{}{}} -\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces \textbf {Representations of a song of \textit {O. rufipes} during the preprocessing stage.} \textbf {a}:~Bandpass-filtered tympanal signal. \textbf {b}:~Signal envelope. \textbf {c}:~Logarithmically scaled envelope. \textbf {d}:~Intensity-adapted envelope. }}{7}{}\protected@file@percent } -\newlabel{fig:pre}{{2}{7}{}{}{}} +\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces \textbf {Representations of a song of \textit {O. rufipes} during the preprocessing stage.} \textbf {a}:~Bandpass-filtered tympanal signal. \textbf {b}:~Signal envelope. \textbf {c}:~Logarithmically scaled envelope. \textbf {d}:~Intensity-adapted envelope. }}{8}{}\protected@file@percent } +\newlabel{fig:pre}{{2}{8}{}{}{}} \@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Feature extraction by individual neurons}{8}{}\protected@file@percent } \newlabel{eq:conv}{{5}{8}{}{}{}} \newlabel{eq:gabor}{{6}{8}{}{}{}} @@ -236,33 +236,39 @@ \@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces Values of phase $\phi $ that are specific for the four major groups of Gabor kernels.}}{9}{}\protected@file@percent } \newlabel{tab:gabor_phases}{{1}{9}{}{}{}} \newlabel{eq:binary}{{9}{9}{}{}{}} -\abx@aux@page{70}{9} -\abx@aux@page{71}{9} -\abx@aux@page{72}{9} -\newlabel{eq:lowpass}{{10}{9}{}{}{}} +\abx@aux@page{70}{10} +\abx@aux@page{71}{10} +\abx@aux@page{72}{10} +\newlabel{eq:lowpass}{{10}{10}{}{}{}} \@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces \textbf {Representations of a song of \textit {O. rufipes} during the feature extraction stage.} Different colors indicate Gabor kernels with different lobe number $n$ and sign, with lighter colors for higher $n$~($1\,\leq \,n\,\leq \,4$; both $+$ and $-$ per $n$; two kernel widths $\sigma $ of $4\,$ms and $32\,$ms per sign). \textbf {a}:~Kernel-specific filter responses. \textbf {b}:~Binary responses. \textbf {c}:~Finalized features. }}{10}{}\protected@file@percent } \newlabel{fig:stages_feat}{{3}{10}{}{}{}} \@writefile{toc}{\contentsline {section}{\numberline {3}Two mechanisms driving the emergence of intensity-invariant song representation}{10}{}\protected@file@percent } -\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Logarithmic compression \& spike-frequency adaptation}{10}{}\protected@file@percent } -\newlabel{eq:toy_env}{{11}{10}{}{}{}} +\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Logarithmic compression \& spike-frequency adaptation}{11}{}\protected@file@percent } +\newlabel{eq:toy_env}{{11}{11}{}{}{}} \newlabel{eq:toy_log}{{12}{11}{}{}{}} \newlabel{eq:toy_highpass}{{13}{11}{}{}{}} -\newlabel{eq:toy_snr}{{14}{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.} Envelope $x_{\text {env}}(t)$ is transformed into logarihmically compressed envelope $x_{\text {dB}}(t)$ and further into intensity-adapted envelope $x_{\text {adapt}}(t)$. Indicated time scale is $5\,$s for both \textbf {a} and \textbf {b} (black bars). \textbf {a}:~Ideally, if $x_{\text {env}}(t)$ consists only of song component $s(t)$ rescaled by $\alpha $, then $x_{\text {adapt}}(t)$ is fully intensity-invariant across all $\alpha $. \textbf {b}:~In practice, $x_{\text {env}}(t)$ also contains fixed-scale noise component $\eta (t)$, which limits the effective intensity invariance of $x_{\text {adapt}}(t)$ to sufficiently large $\alpha $. \textbf {c}:~Ratios of the SD of each representation in \textbf {b} at a given $\alpha $ relative to the SD of the representation for $\alpha =0$ (solid lines). The same ratios for the ideal $x_{\text {adapt}}(t)$ in \textbf {a} are shown for comparison (dashed line). }}{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 the threshold value with regard to variable range but not saturation level.} Kernel response $c_i(t)$ is rescaled by $\alpha $ and transformed into binary response $b_i(t)$ and further into feature $f_i(t)$. Threshold value $\Theta _i$ is set to different percentiles of the the distribution of $c_i(t)$ at $\alpha =1$. Darker colors indicate higher values of $\Theta _i$. Indicated time scale of $500\,$ms is the same for \textbf {a}-\textbf {c} (black bar). \textbf {a}:~50th percentile. \textbf {b}:~75th percentile. \textbf {c}:~100th percentile. \textbf {d}:~Average value of $f_i(t)$ during the song for the different $\Theta _i$ in \textbf {a}-\textbf {c}. }}{13}{}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces \textbf {Intensity invariance by thresholding and temporal averaging depends on the threshold value with regard to variable range but not saturation level.} Kernel response $c_i(t)$ is rescaled by $\alpha $ and transformed into binary response $b_i(t)$ and further into feature $f_i(t)$. Threshold value $\Theta _i$ is set to different percentiles of the the distribution of $c_i(t)$ at $\alpha =1$. Darker colors indicate higher values of $\Theta _i$. Indicated time scale of $100\,$ms is the same for \textbf {a}-\textbf {c} (black bar). \textbf {a}:~50th percentile. \textbf {b}:~75th percentile. \textbf {c}:~100th percentile. \textbf {d}:~Average value of $f_i(t)$ during the song for the different $\Theta _i$ in \textbf {a}-\textbf {c}. }}{13}{}\protected@file@percent } \newlabel{fig:inv_thresh-lp_single}{{5}{13}{}{}{}} -\@writefile{lof}{\contentsline {figure}{\numberline {6}{\ignorespaces \textbf {Intensity invariance by thresholding and temporal averaging depends on noise with regard to variable range but not saturation level.} Kernel response $c_i(t)$ is rescaled by $\alpha $, mixed with fixed-scale noise component $\eta (t)$, and transformed into binary response $b_i(t)$ and further into feature $f_i(t)$. Threshold value $\Theta _i$ is set to different percentiles of the the distribution of $c_i(t)$ at $\alpha =1$. Darker colors indicate higher values of $\Theta _i$. Indicated time scale of $500\,$ms is the same for \textbf {a}-\textbf {c} (black bar). \textbf {a}:~50th percentile. \textbf {b}:~75th percentile. \textbf {c}:~100th percentile. \textbf {d}:~Average value of $f_i(t)$ during the song for the different $\Theta _i$ in \textbf {a}-\textbf {c}. }}{14}{}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {6}{\ignorespaces \textbf {Intensity invariance by thresholding and temporal averaging depends on noise with regard to variable range but not saturation level.} Kernel response $c_i(t)$ is rescaled by $\alpha $, mixed with fixed-scale noise component $\eta (t)$, and transformed into binary response $b_i(t)$ and further into feature $f_i(t)$. Threshold value $\Theta _i$ is set to different percentiles of the the distribution of $c_i(t)$ at $\alpha =1$. Darker colors indicate higher values of $\Theta _i$. Indicated time scale of $100\,$ms is the same for \textbf {a}-\textbf {c} (black bar). \textbf {a}:~50th percentile. \textbf {b}:~75th percentile. \textbf {c}:~100th percentile. \textbf {d}:~Average value of $f_i(t)$ during the song for the different $\Theta _i$ in \textbf {a}-\textbf {c}. }}{14}{}\protected@file@percent } \newlabel{fig:inv_thresh-lp_single_noise}{{6}{14}{}{}{}} -\newlabel{eq:pdf_split}{{15}{15}{}{}{}} -\newlabel{eq:feat_avg}{{16}{15}{}{}{}} -\newlabel{eq:feat_prop}{{17}{15}{}{}{}} +\@writefile{lof}{\contentsline {figure}{\numberline {7}{\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}{{7}{15}{}{}{}} +\@writefile{lof}{\contentsline {figure}{\numberline {8}{\ignorespaces \textbf {Step-wise emergence of intensity invariant song representation along the model pathway.} }}{15}{}\protected@file@percent } +\newlabel{fig:inv_thresh-lp_full}{{8}{15}{}{}{}} +\newlabel{eq:pdf_split}{{15}{16}{}{}{}} +\newlabel{eq:feat_avg}{{16}{16}{}{}{}} +\newlabel{eq:feat_prop}{{17}{16}{}{}{}} \abx@aux@cite{0}{stumpner1991auditory} \abx@aux@segm{0}{0}{stumpner1991auditory} -\@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{toc}{\contentsline {section}{\numberline {4}Discriminating species-specific song\\patterns in feature space}{17}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\numberline {5}Conclusions \& outlook}{17}{}\protected@file@percent } +\abx@aux@page{73}{17} +\@writefile{lof}{\contentsline {figure}{\numberline {9}{\ignorespaces \textbf {} }}{19}{}\protected@file@percent } +\newlabel{}{{9}{19}{}{}{}} \gdef\svg@ink@ver@settings{{\m@ne }{inkscape}{\m@ne }} \abx@aux@read@bbl@mdfivesum{1380DC8C93D2855FDB132CC5A40AD52F} -\gdef \@abspage@last{17} +\gdef \@abspage@last{19} diff --git a/main.blg b/main.blg index 825ae8a..ebd6ca6 100644 --- a/main.blg +++ b/main.blg @@ -1,71 +1,71 @@ [0] Config.pm:307> INFO - This is Biber 2.19 [0] Config.pm:310> INFO - Logfile is 'main.blg' -[35] biber:340> INFO - === Mi Mär 11, 2026, 15:14:06 -[44] Biber.pm:419> INFO - Reading 'main.bcf' -[72] Biber.pm:979> INFO - Found 55 citekeys in bib section 0 -[77] Biber.pm:4419> INFO - Processing section 0 +[38] biber:340> INFO - === Do Mär 19, 2026, 16:33:01 +[45] Biber.pm:419> INFO - Reading 'main.bcf' +[73] Biber.pm:979> INFO - Found 55 citekeys in bib section 0 +[78] Biber.pm:4419> INFO - Processing section 0 [82] Biber.pm:4610> INFO - Looking for bibtex file 'cite.bib' for section 0 -[83] bibtex.pm:1713> INFO - LaTeX decoding ... -[113] bibtex.pm:1519> INFO - Found BibTeX data source 'cite.bib' -[284] UCollate.pm:68> INFO - Overriding locale 'en-US' defaults 'variable = shifted' with 'variable = non-ignorable' -[284] UCollate.pm:68> INFO - Overriding locale 'en-US' defaults 'normalization = NFD' with 'normalization = prenormalized' -[284] Biber.pm:4239> INFO - Sorting list 'nyt/global//global/global' of type 'entry' with template 'nyt' and locale 'en-US' -[284] Biber.pm:4245> INFO - No sort tailoring available for locale 'en-US' -[308] bbl.pm:660> INFO - Writing 'main.bbl' with encoding 'UTF-8' -[318] bbl.pm:763> INFO - Output to main.bbl -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 10, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 21, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 38, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 49, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 58, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 73, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 82, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 91, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 100, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 109, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 118, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 127, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 136, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 157, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 178, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 187, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 196, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 207, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 218, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 229, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 240, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 249, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 258, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 269, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 278, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 289, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 300, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 309, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 328, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 337, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 400, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 419, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 428, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 437, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 456, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 491, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 526, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 535, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 556, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 565, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 576, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 587, warning: 6 characters of junk seen at toplevel -[318] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 619, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 648, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 658, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 667, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 688, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 709, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 720, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 729, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 749, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 766, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 775, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 800, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_yUae/347c261ec4135a5723bef5c751f5078f_41297.utf8, line 817, warning: 6 characters of junk seen at toplevel -[319] Biber.pm:133> INFO - WARNINGS: 55 +[84] bibtex.pm:1713> INFO - LaTeX decoding ... +[115] bibtex.pm:1519> INFO - Found BibTeX data source 'cite.bib' +[293] UCollate.pm:68> INFO - Overriding locale 'en-US' defaults 'normalization = NFD' with 'normalization = prenormalized' +[293] UCollate.pm:68> INFO - Overriding locale 'en-US' defaults 'variable = shifted' with 'variable = non-ignorable' +[293] Biber.pm:4239> INFO - Sorting list 'nyt/global//global/global' of type 'entry' with template 'nyt' and locale 'en-US' +[293] Biber.pm:4245> INFO - No sort tailoring available for locale 'en-US' +[316] bbl.pm:660> INFO - Writing 'main.bbl' with encoding 'UTF-8' +[326] bbl.pm:763> INFO - Output to main.bbl +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 10, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 21, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 38, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 49, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 58, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 73, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 82, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 91, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 100, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 109, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 118, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 127, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 136, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 157, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 178, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 187, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 196, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 207, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 218, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 229, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 240, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 249, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 258, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 269, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 278, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 289, warning: 6 characters of junk seen at toplevel +[326] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 300, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 309, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 328, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 337, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 400, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 419, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 428, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 437, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 456, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 491, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 526, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 535, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 556, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 565, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 576, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 587, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 619, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 648, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 658, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 667, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 688, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 709, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 720, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 729, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 749, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 766, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 775, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 800, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:131> WARN - BibTeX subsystem: /tmp/biber_tmp_fJKN/347c261ec4135a5723bef5c751f5078f_21083.utf8, line 817, warning: 6 characters of junk seen at toplevel +[327] Biber.pm:133> INFO - WARNINGS: 55 diff --git a/main.fdb_latexmk b/main.fdb_latexmk index 45ede87..6ea9704 100644 --- a/main.fdb_latexmk +++ b/main.fdb_latexmk @@ -1,14 +1,14 @@ # Fdb version 4 -["biber main"] 1773238445.97958 "main.bcf" "main.bbl" "main" 1773392777.69214 0 +["biber main"] 1773934381.64397 "main.bcf" "main.bbl" "main" 1774003703.72889 0 "cite.bib" 1770904753.08918 27483 4290db0c91f7b5055e25472ef913f6b4 "" - "main.bcf" 1773392777.63678 112931 2a478116d80ebb1ada7083a24facd6e3 "pdflatex" + "main.bcf" 1774003703.5967 112931 2a478116d80ebb1ada7083a24facd6e3 "pdflatex" (generated) "main.bbl" "main.blg" (rewritten before read) -["pdflatex"] 1773392776.7873 "/home/hartling/phd/paper/paper_2025/main.tex" "main.pdf" "main" 1773392777.69235 0 +["pdflatex"] 1774003702.2857 "/home/hartling/phd/paper/paper_2025/main.tex" "main.pdf" "main" 1774003703.7291 0 "/etc/texmf/web2c/texmf.cnf" 1761560044.43676 475 c0e671620eb5563b2130f56340a5fde8 "" - "/home/hartling/phd/paper/paper_2025/main.tex" 1773312783.44267 47631 f6b9c9e8caccb02783f29486663acfa3 "" + "/home/hartling/phd/paper/paper_2025/main.tex" 1773934444.28996 48517 9087d4f689a47c904bde7fa096405f41 "" "/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 "" @@ -152,15 +152,18 @@ "/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map" 1761648465.84635 5472669 54eaf61a88b6b7896ebd0dac973cb29c "" "/var/lib/texmf/web2c/pdftex/pdflatex.fmt" 1761648508 8213325 7fd20752ab46ff9aa583e4973d7433df "" "figures/fig_auditory_pathway.pdf" 1771593904.14638 1153923 3df8539421fd21dc866cc8d320bd9b1d "" - "figures/fig_feat_stages.pdf" 1771841347.81651 8600157 89f9276167cc096f9adce052152edd70 "" - "figures/fig_invariance_log_hp.pdf" 1773239234.07343 478578 b583c316e5e715032fa338984f274dd8 "" - "figures/fig_invariance_thresh_lp_single.pdf" 1773392682.53371 931926 00b6c0232c328feb78271f3a7ad10bd9 "" - "figures/fig_invariance_thresh_lp_single_noise.pdf" 1773392714.27939 1401197 6c69dc364ff57747e40f8a0ab4353fa4 "" - "figures/fig_pre_stages.pdf" 1771841345.77353 440442 263f9bd4a3bca8e0653ac0a4c4a8da2c "" - "main.aux" 1773392777.63078 14838 a4d8e057160ee865618aebf9c55cc9ce "pdflatex" - "main.bbl" 1773238446.59287 91039 1380dc8c93d2855fdb132cc5a40ad52f "biber main" - "main.run.xml" 1773392777.63678 2335 a049bc26a7f032e842ce55de5bc38328 "pdflatex" - "main.tex" 1773312783.44267 47631 f6b9c9e8caccb02783f29486663acfa3 "" + "figures/fig_feat_stages.pdf" 1774002994.98767 11091006 565fe951f1255c121429a060082398f5 "" + "figures/fig_invariance_full.pdf" 1773819860.38414 149803772 fccb17ff409abc968506436f5f2a988b "" + "figures/fig_invariance_log_hp.pdf" 1774003683.58788 575653 1d22d01e8ec1887d589b6c390cb525a5 "" + "figures/fig_invariance_thresh_lp_single.pdf" 1773738083.70309 580357 3681b066ae31e650d9261f435fcd92af "" + "figures/fig_invariance_thresh_lp_single_noise.pdf" 1773744879.7418 944314 a7ad50e5da0a6fee3e412405112b2452 "" + "figures/fig_invariance_thresh_lp_species.pdf" 1773741140.93995 47573 9dd8a2281ce467803dd2a7b74ff3373e "" + "figures/fig_noise_env_sd_conversion.pdf" 1773997868.36537 46476 7c9bed06eeb2454123a52c7edcf50a9f "" + "figures/fig_pre_stages.pdf" 1774002992.74268 449426 5762be15627fe5d8b6d108b7ea18db44 "" + "main.aux" 1774003703.5907 15511 e97ecd7b1fe5a4dcc728b64236d3ed04 "pdflatex" + "main.bbl" 1773934382.23323 91039 1380dc8c93d2855fdb132cc5a40ad52f "biber main" + "main.run.xml" 1774003703.5967 2335 a049bc26a7f032e842ce55de5bc38328 "pdflatex" + "main.tex" 1773934444.28996 48517 9087d4f689a47c904bde7fa096405f41 "" (generated) "main.aux" "main.bcf" diff --git a/main.fls b/main.fls index dcc555d..7832fbe 100644 --- a/main.fls +++ b/main.fls @@ -303,6 +303,21 @@ INPUT ./figures/fig_invariance_thresh_lp_single_noise.pdf INPUT ./figures/fig_invariance_thresh_lp_single_noise.pdf INPUT ./figures/fig_invariance_thresh_lp_single_noise.pdf INPUT ./figures/fig_invariance_thresh_lp_single_noise.pdf +INPUT ./figures/fig_invariance_thresh_lp_species.pdf +INPUT ./figures/fig_invariance_thresh_lp_species.pdf +INPUT ./figures/fig_invariance_thresh_lp_species.pdf +INPUT ./figures/fig_invariance_thresh_lp_species.pdf +INPUT ./figures/fig_invariance_thresh_lp_species.pdf +INPUT ./figures/fig_invariance_full.pdf +INPUT ./figures/fig_invariance_full.pdf +INPUT ./figures/fig_invariance_full.pdf +INPUT ./figures/fig_invariance_full.pdf +INPUT ./figures/fig_invariance_full.pdf +INPUT ./figures/fig_noise_env_sd_conversion.pdf +INPUT ./figures/fig_noise_env_sd_conversion.pdf +INPUT ./figures/fig_noise_env_sd_conversion.pdf +INPUT ./figures/fig_noise_env_sd_conversion.pdf +INPUT ./figures/fig_noise_env_sd_conversion.pdf INPUT main.aux INPUT main.run.xml OUTPUT main.run.xml diff --git a/main.log b/main.log index 6e1de08..c1a444b 100644 --- a/main.log +++ b/main.log @@ -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) 13 MAR 2026 10:06 +This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023/Debian) (preloaded format=pdflatex 2025.10.28) 20 MAR 2026 11:48 entering extended mode restricted \write18 enabled. file:line:error style messages enabled. @@ -747,42 +747,59 @@ LaTeX Warning: Text page 6 contains only floats. Overfull \vbox (0.8319pt too high) has occurred while \output is active [] [6 <./figures/fig_auditory_pathway.pdf>] - + File: figures/fig_pre_stages.pdf Graphic file (type pdf) Package pdftex.def Info: figures/fig_pre_stages.pdf used on input line 421. -(pdftex.def) Requested size: 483.69687pt x 181.38585pt. - [7 <./figures/fig_pre_stages.pdf>] [8] +(pdftex.def) Requested size: 483.69687pt x 241.84782pt. + [7] [8 <./figures/fig_pre_stages.pdf>] Overfull \hbox (42.89445pt too wide) in paragraph at lines 514--523 \OT1/cmr/m/n/12 glion ([]; []; []). [] - +[9] + File: figures/fig_feat_stages.pdf Graphic file (type pdf) Package pdftex.def Info: figures/fig_feat_stages.pdf used on input line 535. -(pdftex.def) Requested size: 483.69687pt x 181.38585pt. -[9] [10 <./figures/fig_feat_stages.pdf>] +(pdftex.def) Requested size: 483.69687pt x 241.84782pt. + [10 <./figures/fig_feat_stages.pdf>] [11] File: figures/fig_invariance_log_hp.pdf Graphic file (type pdf) Package pdftex.def Info: figures/fig_invariance_log_hp.pdf used on input line 625. (pdftex.def) Requested size: 483.69687pt x 241.84782pt. - [11] - + File: figures/fig_invariance_thresh_lp_single.pdf Graphic file (type pdf) Package pdftex.def Info: figures/fig_invariance_thresh_lp_single.pdf used on input line 654. (pdftex.def) Requested size: 483.69687pt x 241.84782pt. [12 <./figures/fig_invariance_log_hp.pdf>] - + File: figures/fig_invariance_thresh_lp_single_noise.pdf Graphic file (type pdf) Package pdftex.def Info: figures/fig_invariance_thresh_lp_single_noise.pdf used on input line 677. (pdftex.def) Requested size: 483.69687pt x 241.84782pt. - [13 <./figures/fig_invariance_thresh_lp_single.pdf>] [14 <./figures/fig_invariance_thresh_lp_single_noise.pdf>] [15 + [13 <./figures/fig_invariance_thresh_lp_single.pdf>] [14 <./figures/fig_invariance_thresh_lp_single_noise.pdf>] + +File: figures/fig_invariance_thresh_lp_species.pdf Graphic file (type pdf) + +Package pdftex.def Info: figures/fig_invariance_thresh_lp_species.pdf used on input line 701. +(pdftex.def) Requested size: 483.69687pt x 241.84782pt. + +File: figures/fig_invariance_full.pdf Graphic file (type pdf) + +Package pdftex.def Info: figures/fig_invariance_full.pdf used on input line 711. +(pdftex.def) Requested size: 483.69687pt x 241.84782pt. + [15 -] [16] [17] (./main.aux) + <./figures/fig_invariance_thresh_lp_species.pdf> <./figures/fig_invariance_full.pdf>] [16] [17] + +File: figures/fig_noise_env_sd_conversion.pdf Graphic file (type pdf) + +Package pdftex.def Info: figures/fig_noise_env_sd_conversion.pdf used on input line 870. +(pdftex.def) Requested size: 483.69687pt x 241.84782pt. + [18] [19 <./figures/fig_noise_env_sd_conversion.pdf>] (./main.aux) *********** LaTeX2e <2023-11-01> patch level 1 L3 programming layer <2024-01-22> @@ -792,18 +809,18 @@ Package logreq Info: Writing requests to 'main.run.xml'. ) Here is how much of TeX's memory you used: - 20741 strings out of 474222 - 447377 string characters out of 5748732 + 20765 strings out of 474222 + 448444 string characters out of 5748732 1937975 words of memory out of 5000000 - 42731 multiletter control sequences out of 15000+600000 + 42755 multiletter control sequences out of 15000+600000 569394 words of font info for 79 fonts, out of 8000000 for 9000 1143 hyphenation exceptions out of 8191 94i,19n,93p,1214b,1732s stack positions out of 10000i,1000n,20000p,200000b,200000s -Output written on main.pdf (17 pages, 13160382 bytes). +Output written on main.pdf (19 pages, 164827394 bytes). PDF statistics: - 1394 PDF objects out of 1440 (max. 8388607) - 802 compressed objects within 9 object streams + 1568 PDF objects out of 1728 (max. 8388607) + 861 compressed objects within 9 object streams 0 named destinations out of 1000 (max. 500000) - 43 words of extra memory for PDF output out of 10000 (max. 10000000) + 58 words of extra memory for PDF output out of 10000 (max. 10000000) diff --git a/main.pdf b/main.pdf index 96d565a..7763b8b 100644 Binary files a/main.pdf and b/main.pdf differ diff --git a/main.synctex.gz b/main.synctex.gz index e1084c1..f939193 100644 Binary files a/main.synctex.gz and b/main.synctex.gz differ diff --git a/main.tex b/main.tex index 8044a73..68c57b9 100644 --- a/main.tex +++ b/main.tex @@ -660,7 +660,7 @@ the signal for reliable song recognition. feature $f_i(t)$. Threshold value $\thr$ is set to different percentiles of the the distribution of $c_i(t)$ at $\sca=1$. Darker colors indicate higher values of - $\thr$. Indicated time scale of $500\,$ms is the same for + $\thr$. Indicated time scale of $100\,$ms is the same for \textbf{a}-\textbf{c} (black bar). \textbf{a}:~50th percentile. \textbf{b}:~75th percentile. @@ -684,7 +684,7 @@ the signal for reliable song recognition. $f_i(t)$. Threshold value $\thr$ is set to different percentiles of the the distribution of $c_i(t)$ at $\sca=1$. Darker colors indicate higher values of $\thr$. - Indicated time scale of $500\,$ms is the same for + Indicated time scale of $100\,$ms is the same for \textbf{a}-\textbf{c} (black bar). \textbf{a}:~50th percentile. \textbf{b}:~75th percentile. @@ -696,6 +696,26 @@ the signal for reliable song recognition. \end{figure} \FloatBarrier +\begin{figure}[!ht] + \centering + \includegraphics[width=\textwidth]{figures/fig_invariance_thresh_lp_species.pdf} + \caption{\textbf{Feature representation of different species-specific songs + saturates at different points in feature space.} + } + \label{fig:inv_thresh-lp_species} +\end{figure} +\FloatBarrier + +\begin{figure}[!ht] + \centering + \includegraphics[width=\textwidth]{figures/fig_invariance_full.pdf} + \caption{\textbf{Step-wise emergence of intensity invariant song + representation along the model pathway.} + } + \label{fig:inv_thresh-lp_full} +\end{figure} +\FloatBarrier + The second key mechanism for the emergence of intensity invariance along the model pathway takes place during the transformation of the kernel responses $c_i(t)$ over the binary responses $b_i(t)$ into the finalized features @@ -844,4 +864,14 @@ $\rightarrow$ Graded again but highly decorrelated from the acoustic stimulus\\ $\rightarrow$ Parameters of a behavioral response may be graded (e.g. approach speed), initiation of one behavior over another is categorical (e.g. approach/stay) + +\begin{figure}[!ht] + \centering + \includegraphics[width=\textwidth]{figures/fig_noise_env_sd_conversion.pdf} + \caption{\textbf{} + } + \label{} +\end{figure} +\FloatBarrier + \end{document} \ No newline at end of file diff --git a/python/fig_env_sd_conversion.py b/python/fig_env_sd_conversion.py new file mode 100644 index 0000000..8ce1788 --- /dev/null +++ b/python/fig_env_sd_conversion.py @@ -0,0 +1,111 @@ +import plotstyle_plt +import numpy as np +import matplotlib.pyplot as plt +from plot_functions import xlabel, ylabel, strip_zeros, letter_subplots + +# GENERAL SETTINGS: +data_path = '../data/inv/noise_env/sd_conversion.npz' +save_path = '../figures/fig_noise_env_sd_conversion.pdf' + +# PLOT SETTINGS: +fig_kwargs = dict( + figsize=(32/2.54, 16/2.54), + nrows=2, + ncols=1, + sharex=True, + sharey=True, + gridspec_kw=dict( + wspace=0, + hspace=0.1, + left=0.065, + right=0.98, + bottom=0.08, + top=0.95, + ) +) +grid_line_kwargs = dict( + visible=True, + which='major', + axis='both', + color='k', + lw=0.5, +) +trial_kwargs = dict( + color='k', + alpha=0.5, + lw=0.5, +) +line_kwargs = dict( + color='black', + lw=1, +) +fill_kwargs = dict( + color='k', + alpha=0.5, +) +xlabels = dict( + bottom='$\\text{scale }\\alpha$', +) +ylabels = dict( + top='$\\sigma_{\\eta}\\,(PLACEHOLDER \\,\\text{realizations})$', + bottom='$\\sigma_{\\eta}\\,(\\text{mean}\\,\\pm\\,\\text{SD})$', +) +xlab_kwargs = dict( + y=0, + fontsize=20, + ha='center', + va='bottom', +) +ylab_kwargs = dict( + x=0, + fontsize=20, + ha='center', + va='top', +) +title_kwargs = dict( + t='$\\sigma_{\\text{filt}}\\,=$', + x=0.5, + y=1, + ha='center', + va='top', + fontsize=20, +) +letter_kwargs = dict( + x=0.005, + y=0.99, + fontsize=22, + ha='left', + va='top', +) + +# Fetch data: +data = dict(np.load('../data/inv/noise_env/sd_conversion.npz')) +n = data['n_trials'] + +# Adjust parameters: +ylabels['top'] = f'$\\sigma_{{\\eta}}\\,({data["n_trials"]}\\text{{ realizations}})$' +title_kwargs['t'] += f'$\\,{strip_zeros(data["sd_factor"])}$' + +# Prepare graph: +fig, (ax1, ax2) = plt.subplots(**fig_kwargs) +fig.suptitle(**title_kwargs) +ax1.grid(**grid_line_kwargs) +ax1.set_xlim(data['scales'][0], data['scales'][-1]) +ax1.set_xscale('symlog', linthresh=data['scales'][1], linscale=0.5) +ax1.set_ylim(0.4, 1.2) +ylabel(ax1, ylabels['top'], transform=fig.transFigure, **ylab_kwargs) +ax2.grid(**grid_line_kwargs) +xlabel(ax2, xlabels['bottom'], transform=fig.transFigure, **xlab_kwargs) +ylabel(ax2, ylabels['bottom'], transform=fig.transFigure, **ylab_kwargs) +letter_subplots((ax1, ax2), **letter_kwargs) + +# Plot individual trials: +ax1.plot(data['scales'], data['trials'], **trial_kwargs) + +# Plot mean and spread across trials: +ax2.plot(data['scales'], data['mean'], **line_kwargs) +ax2.fill_between(data['scales'], data['mean'] - data['spread'], data['mean'] + data['spread'], **fill_kwargs) + +if save_path is not None: + fig.savefig(save_path) +plt.show() diff --git a/python/fig_invariance_full.py b/python/fig_invariance_full.py index 7e7dafe..4e38e54 100644 --- a/python/fig_invariance_full.py +++ b/python/fig_invariance_full.py @@ -5,46 +5,37 @@ import matplotlib.pyplot as plt from itertools import product from thunderhopper.modeltools import load_data from color_functions import load_colors -from plot_functions import hide_axis, ylimits, xlabel, ylabel, plot_line, plot_barcode, strip_zeros +from plot_functions import hide_axis, ylimits, xlabel, ylabel, title_subplot,\ + plot_line, plot_barcode, strip_zeros, time_bar, super_xlabel from IPython import embed -def add_snip_axes(fig, grid_kwargs): - grid = fig.add_gridspec(**grid_kwargs) - axes = np.zeros((grid.nrows, grid.ncols), dtype=object) - for i, j in product(range(grid.nrows), range(grid.ncols)): - axes[i, j] = fig.add_subplot(grid[i, j]) - [hide_axis(ax, 'left') for ax in axes.flatten()] - [hide_axis(ax, 'bottom') for ax in axes.flatten()] - return axes - def plot_snippets(axes, time, snippets, ymin=None, ymax=None, **kwargs): ymin, ymax = ylimits(snippets, minval=ymin, maxval=ymax, pad=0.05) - for ax, snippet in zip(axes, snippets.T): - plot_line(ax, time, snippet, ymin=ymin, ymax=ymax, **kwargs) + for i, ax in enumerate(axes): + plot_line(ax, time, snippets[:, ..., i], ymin=ymin, ymax=ymax, **kwargs) return None -def plot_bi_snippets(axes, time, binary, **kwargs): - for ax, binary in zip(axes, binary.T): - plot_barcode(ax, time, binary[:, None], **kwargs) +def plot_bi_snippets(axes, time, snippets, **kwargs): + for i, ax in enumerate(axes): + plot_barcode(ax, time, snippets[:, ..., i], **kwargs) return None - # GENERAL SETTINGS: target = 'Omocestus_rufipes' -data_paths = glob.glob(f'../data/processed/{target}*.npz') -stages = ['filt', 'env', 'log', 'inv', 'conv', 'bi', 'feat'] +data_paths = glob.glob(f'../data/inv/full/{target}*.npz') +stages = ['raw', 'filt', 'env', 'log', 'inv', 'conv', 'bi', 'feat'] load_kwargs = dict( files=stages, - keywords=['scales', 'measure', 'spread'] + keywords=['scales', 'snip', 'measure'] ) -save_path = None#'../figures/fig_invariance_full.pdf' +save_path = '../figures/fig_invariance_full.pdf' # GRAPH SETTINGS: fig_kwargs = dict( figsize=(32/2.54, 16/2.54), ) super_grid_kwargs = dict( - nrows=len(stages), + nrows=1, ncols=3, wspace=0, hspace=0, @@ -54,104 +45,124 @@ super_grid_kwargs = dict( top=1 ) subfig_specs = dict( - **{stage: (slice(0, -1), i) for i, stage in enumerate(stages)}, - big=(slice(None), -1) + snip=(slice(None), slice(0, -1)), + big=(slice(None), -1), ) -stage_grid_kwargs = dict( - nrows=1, +snip_grid_kwargs = dict( + nrows=len(stages), ncols=None, - wspace=0.05, - hspace=0, - left=0.07, + wspace=0.1, + hspace=0.4, + left=0.15, right=0.95, - bottom=0.15, - top=0.9 + bottom=0.08, + top=0.95 ) big_grid_kwargs = dict( nrows=1, ncols=1, wspace=0, hspace=0, - left=0.15, + left=0.2, right=0.96, - bottom=0.1, + bottom=0.08, top=0.95 ) # PLOT SETTINGS: colors = load_colors('../data/stage_colors.npz') -lw_snippets = dict( +colors['raw'] = "#000000" +lw = dict( raw=0.25, filt=0.25, - env=0.5, - log=0.5, - inv=0.5, - conv=0.5, - bi=0.01, - feat=2 + env=0.25, + log=0.25, + inv=0.25, + conv=0.25, + bi=0, + feat=1, + big=3 ) -lw_big = 3 xlabels = dict( - analysis='scale $\\alpha$', + snip='time [s]', + big='scale $\\alpha$', ) -xlab_analysis_kwargs = dict( - y=0.01, +ylabels = dict( + raw='$x$', + filt='$x_{\\text{filt}}$', + env='$x_{\\text{env}}$', + log='$x_{\\text{log}}$', + inv='$x_{\\text{inv}}$', + conv='$c_i$', + bi='$b_i$', + feat='$f_i$', + big='norm. intensity measure' +) +xlab_snip_kwargs = dict( + y=0, fontsize=16, ha='center', va='bottom', ) -ylabels = dict( - conv='$c_i$', - bi='$b_i$', - feat='$f_i$', - analysis='ratio $\\text{SD}_{\\alpha}\\,/\\,\\text{SD}_{\\min[\\alpha]}$', - # analysis='ratio $\\sigma_{\\alpha}\\,/\\,\\sigma_{\\min[\\alpha]}$', +xlab_big_kwargs = dict( + y=0, + fontsize=16, + ha='center', + va='bottom', ) ylab_snip_kwargs = dict( - x=0.01, + x=0, fontsize=20, rotation=0, ha='left', - va='center', + va='center' ) -ylab_analysis_kwargs = dict( - x=0.02, +ylab_big_kwargs = dict( + x=0, fontsize=16, ha='center', va='top', ) -# xloc = dict( -# analysis=10, -# ) -# letter_snip_kwargs = dict( -# x=0.02, -# y=1, -# ha='left', -# va='top', -# fontsize=22, -# fontweight='bold' -# ) -# letter_analysis_kwargs = dict( -# x=0, -# y=1, -# ha='left', -# va='top', -# fontsize=22, -# fontweight='bold' -# ) -# bar_time = 5 -# bar_kwargs = dict( -# y0=0.7, -# y1=0.8, -# color='k', -# lw=0, -# ) -# spread_kwargs = dict( -# alpha=0.3, -# lw=0, -# zorder=0 -# ) -# kernel_ind = 0 +yloc = dict( + raw=500, + filt=500, + env=250, + log=25, + inv=10, + conv=1, + feat=1, +) +title_kwargs = dict( + x=0.5, + yref=1, + ha='center', + va='top', + fontsize=16, +) +letter_snip_kwargs = dict( + x=0.02, + y=1, + ha='left', + va='top', + fontsize=22, + fontweight='bold' +) +letter_big_kwargs = dict( + x=0, + y=1, + ha='left', + va='top', + fontsize=22, + fontweight='bold' +) +bar_time = 5 +bar_kwargs = dict( + y0=0.8, + y1=0.9, + color='k', + lw=0, +) + # EXECUTION: for data_path in data_paths: @@ -159,82 +170,95 @@ for data_path in data_paths: # Load invariance data: data, config = load_data(data_path, **load_kwargs) - t_full = np.arange(data['conv'].shape[0]) / config['env_rate'] + t_full = np.arange(data['snip_raw'].shape[0]) / config['rate'] - # Reduce snippet data to kernel subset: - data['conv'] = data['conv'][:, kernel_ind] - data['bi'] = data['bi'][:, kernel_ind] - data['feat'] = data['feat'][:, kernel_ind] + # Adjust grid parameters: + snip_grid_kwargs['ncols'] = data['example_scales'].size # Prepare overall graph: fig = plt.figure(**fig_kwargs) super_grid = fig.add_gridspec(**super_grid_kwargs) - # Prepare pure-song snippet axes: - pure_subfig = fig.add_subfigure(super_grid[subfig_specs['pure']]) - pure_grid_kwargs['nrows' if pure_grid_kwargs['nrows'] is None else 'ncols'] = data['example_scales'].size - pure_axes = add_snip_axes(pure_subfig, pure_grid_kwargs) - for ax, stage in zip(pure_axes[:, 0], stages): - ylabel(ax, ylabels[stage], **ylab_snip_kwargs, - transform=pure_subfig.transSubfigure) - for ax, scale in zip(pure_axes[snip_specs['conv']], data['example_scales']): - ax.set_title(f'$\\alpha={strip_zeros(scale)}$') - pure_subfig.text(s='a', **letter_snip_kwargs) + # Prepare stage-specific snippet axes: + snip_subfig = fig.add_subfigure(super_grid[subfig_specs['snip']]) + snip_grid = snip_subfig.add_gridspec(**snip_grid_kwargs) + snip_axes = np.zeros((snip_grid.nrows, snip_grid.ncols), dtype=object) + for i, j in product(range(snip_grid.nrows), range(snip_grid.ncols)): + ax = snip_subfig.add_subplot(snip_grid[i, j]) + ax.set_xlim(t_full[0], t_full[-1]) + hide_axis(ax, 'bottom') + if i == 0: + title = f'$\\alpha={strip_zeros(data["example_scales"][j])}$' + title_subplot(ax, title, ref=snip_subfig, **title_kwargs) + if j == 0: + ylabel(ax, ylabels[stages[i]], **ylab_snip_kwargs, transform=snip_subfig.transSubfigure) + else: + hide_axis(ax, 'left') + if stages[i] != 'bi': + ax.yaxis.set_major_locator(plt.MultipleLocator(yloc[stages[i]])) + snip_axes[i, j] = ax + super_xlabel(xlabels['snip'], snip_subfig, snip_axes[-1, 0], snip_axes[-1, -1], **xlab_snip_kwargs) + time_bar(snip_axes[0, 0], bar_time, **bar_kwargs) - # Prepare analysis axis: - analysis_subfig = fig.add_subfigure(super_grid[subfig_specs['analysis']]) - analysis_grid = analysis_subfig.add_gridspec(**analysis_grid_kwargs) - analysis_ax = analysis_subfig.add_subplot(analysis_grid[0, 0]) - analysis_ax.set_xlim(data['scales'].min(), data['scales'].max()) - analysis_ax.xaxis.set_major_locator(plt.MultipleLocator(xloc['analysis'])) - xlabel(analysis_ax, xlabels['analysis'], **xlab_analysis_kwargs, - transform=analysis_subfig.transSubfigure) - # analysis_ax.set_yscale('log') - ylabel(analysis_ax, ylabels['analysis'], **ylab_analysis_kwargs, - transform=analysis_subfig.transSubfigure) - analysis_subfig.text(s='c', **letter_analysis_kwargs) + # Prepare single analysis axis: + big_subfig = fig.add_subfigure(super_grid[subfig_specs['big']]) + big_grid = big_subfig.add_gridspec(**big_grid_kwargs) + big_ax = big_subfig.add_subplot(big_grid[0, 0]) + big_ax.set_xlim(data['scales'].min(), data['scales'].max()) + big_ax.set_xscale('symlog', linthresh=data['scales'][1], linscale=0.5) + big_ax.set_yscale('symlog', linthresh=0.01, linscale=0.1) + xlabel(big_ax, xlabels['big'], **xlab_big_kwargs, transform=big_subfig.transSubfigure) + ylabel(big_ax, ylabels['big'], **ylab_big_kwargs, transform=big_subfig.transSubfigure) - # Plot pure-song kernel response snippets: - plot_snippets(pure_axes[snip_specs['conv']], t_full, data['conv'], - c=colors['conv'], lw=lw_snippets['conv']) + # Plot raw snippets: + plot_snippets(snip_axes[0, :], t_full, data['snip_raw'], + c=colors['raw'], lw=lw['raw']) - # Plot pure-song binary snippets: - plot_bi_snippets(pure_axes[snip_specs['bi']], t_full, data['bi'], - color=colors['bi'], lw=0) + # Plot filtered snippets: + plot_snippets(snip_axes[1, :], t_full, data['snip_filt'], + c=colors['filt'], lw=lw['filt']) - # Plot pure-song feature snippets: - plot_snippets(pure_axes[snip_specs['feat']], t_full, data['feat'], - ymin=0, ymax=1, c=colors['feat'], lw=lw_snippets['feat']) + # Plot envelope snippets: + plot_snippets(snip_axes[2, :], t_full, data['snip_env'], + ymin=0, c=colors['env'], lw=lw['env']) - # Indicate time scale: - time_bar(pure_axes[snip_specs['conv']][0], bar_time, **bar_kwargs) + # Plot logarithmic snippets: + plot_snippets(snip_axes[3, :], t_full, data['snip_log'], + ymax=0, c=colors['log'], lw=lw['log']) - # # Plot noise-song kernel response snippets: - # plot_snippets(noise_axes[snip_specs['conv']], t_full, noise_data['conv'], - # c=colors['conv'], lw=lw_snippets['conv']) + # Plot invariant snippets: + plot_snippets(snip_axes[4, :], t_full, data['snip_inv'], + c=colors['inv'], lw=lw['inv']) - # # Plot noise-song binary snippets: - # plot_bi_snippets(noise_axes[snip_specs['bi']], t_full, noise_data['bi'], - # color=colors['bi'], lw=0) + # Plot kernel response snippets: + plot_snippets(snip_axes[5, :], t_full, data['snip_conv'], + c=colors['conv'], lw=lw['conv']) - # # Plot noise-song feature snippets: - # plot_snippets(noise_axes[snip_specs['feat']], t_full, noise_data['feat'], - # ymin=0, ymax=1, c=colors['feat'], lw=lw_snippets['feat']) + # Plot binary snippets: + plot_bi_snippets(snip_axes[6, :], t_full, data['snip_bi'], + color=colors['bi'], lw=lw['bi']) - # # Indicate time scale: - # time_bar(noise_axes[snip_specs['conv']][0], bar_time, **bar_kwargs) + # Plot feature snippets: + plot_snippets(snip_axes[7, :], t_full, data['snip_feat'], + ymin=0, ymax=1, c=colors['feat'], lw=lw['feat']) - # Plot noise-song SD ratios (limited): - analysis_ax.plot(data['scales'], data['measure_conv'], - c=colors['conv'], lw=lw_analysis) - lower, upper = data['spread_conv'] - analysis_ax.fill_between(data['scales'], lower, upper, - color=colors['conv'], **spread_kwargs) - analysis_ax.plot(data['scales'], data['measure_feat'], - c=colors['feat'], lw=lw_analysis) - lower, upper = data['spread_feat'] - analysis_ax.fill_between(data['scales'], lower, upper, - color=colors['feat'], **spread_kwargs) + # Analysis results: + for stage in stages: + key = f'measure_{stage}' + if stage == 'bi': + continue + # Min-max normalization: + base_ind = np.argmin(data['scales']) + data[key] -= data[key][base_ind, ...] + data[key] /= data[key].max(axis=0) + + # Condense measure: + if stage in ['conv', 'feat']: + data[key] = np.nanmedian(data[key], axis=1) + + # Plot measure over scales: + big_ax.plot(data['scales'], data[key], + c=colors[stage], lw=lw['big']) if save_path is not None: fig.savefig(save_path) diff --git a/python/fig_invariance_log-hp.py b/python/fig_invariance_log-hp.py index fd57c58..a522628 100644 --- a/python/fig_invariance_log-hp.py +++ b/python/fig_invariance_log-hp.py @@ -5,9 +5,9 @@ from itertools import product from thunderhopper.filetools import search_files from thunderhopper.modeltools import load_data from color_functions import load_colors -from plot_functions import hide_axis, ylimits, xlabel, ylabel,\ - plot_line, strip_zeros, time_bar,\ - letter_subplot, letter_subplots +from plot_functions import hide_axis, ylimits, xlabel, ylabel, hide_ticks,\ + plot_line, strip_zeros, time_bar, zoom_inset,\ + letter_subplot, letter_subplots, title_subplot from IPython import embed def add_snip_axes(fig, grid_kwargs): @@ -15,26 +15,31 @@ def add_snip_axes(fig, grid_kwargs): axes = np.zeros((grid.nrows, grid.ncols), dtype=object) for i, j in product(range(grid.nrows), range(grid.ncols)): axes[i, j] = fig.add_subplot(grid[i, j]) - [hide_axis(ax, 'left') for ax in axes.flatten()] + [hide_axis(ax, 'left') for ax in axes[:, 1:].flatten()] [hide_axis(ax, 'bottom') for ax in axes.flatten()] return axes def plot_snippets(axes, time, snippets, ymin=None, ymax=None, **kwargs): ymin, ymax = ylimits(snippets, minval=ymin, maxval=ymax, pad=0.05) + handles = [] for ax, snippet in zip(axes, snippets.T): - plot_line(ax, time, snippet, ymin=ymin, ymax=ymax, **kwargs) - return None + handles.extend(plot_line(ax, time, snippet, ymin=ymin, ymax=ymax, **kwargs)) + return handles # GENERAL SETTINGS: +compute_ratios = True target = 'Omocestus_rufipes' data_paths = search_files(target, excl='noise', dir='../data/inv/log_hp/') stages = ['env', 'log', 'inv'] load_kwargs = dict( files=stages, - keywords=['scales', 'measure'] + keywords=['scales', 'snip', 'measure'] ) save_path = '../figures/fig_invariance_log_hp.pdf' +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')} # GRAPH SETTINGS: fig_kwargs = dict( @@ -42,7 +47,7 @@ fig_kwargs = dict( ) super_grid_kwargs = dict( nrows=2, - ncols=2, + ncols=3, wspace=0, hspace=0, left=0, @@ -51,99 +56,127 @@ super_grid_kwargs = dict( top=1 ) subfig_specs = dict( - pure=(0, 0), - noise=(1, 0), - analysis=(slice(None), 1) + pure=(0, slice(0, -1)), + noise=(1, slice(0, -1)), + big=(slice(None), -1), ) -pure_grid_kwargs = dict( +snip_grid_kwargs = dict( nrows=len(stages), ncols=None, - wspace=0.05, - hspace=0.1, - left=0.13, + wspace=0.1, + hspace=0.15, + left=0.16, right=0.95, - bottom=0.15, - top=0.9 + bottom=0.1, + top=0.94, + height_ratios=[1, 2, 1] ) -noise_grid_kwargs = dict( - nrows=len(stages), - ncols=None, - wspace=0.05, - hspace=0.1, - left=0.13, - right=0.95, - bottom=0.15, - top=0.9 -) -analysis_grid_kwargs = dict( - nrows=1, +big_grid_kwargs = dict( + nrows=2, ncols=1, wspace=0, - hspace=0, - left=0.15, + hspace=0.1, + left=0.19, right=0.96, - bottom=0.1, - top=0.95 + bottom=0.09, + top=0.98 ) -snip_specs = dict( - env=(0, slice(None)), - log=(1, slice(None)), - inv=(2, slice(None)) +anchor_kwargs = dict( + aspect='equal', + adjustable='box', + anchor=(0.5, 0.5) ) # PLOT SETTINGS: +fs = dict( + lab_norm=16, + lab_tex=20, + letter=22, + tit_norm=16, + tit_tex=20, +) colors = load_colors('../data/stage_colors.npz') lw_snippets = 0.5 -lw_analysis = 3 +lw_big = 3 xlabels = dict( - analysis='scale $\\alpha$', -) -xlab_analysis_kwargs = dict( - y=0.01, - fontsize=16, - ha='center', - va='bottom', + big='scale $\\alpha$', ) ylabels = dict( env='$x_{\\text{env}}$', log='$x_{\\text{dB}}$', inv='$x_{\\text{adapt}}$', - analysis='ratio $\\text{SD}_{\\alpha}\\,/\\,\\text{SD}_{\\min[\\alpha]}$', - # analysis='ratio $\\sigma_{\\alpha}\\,/\\,\\sigma_{\\min[\\alpha]}$', + big='$\\sigma_{\\alpha}\\,/\\,\\sigma_{0}$', +) +xlab_big_kwargs = dict( + y=0, + fontsize=fs['lab_norm'], + ha='center', + va='bottom', ) ylab_snip_kwargs = dict( - x=0.01, - fontsize=20, + x=0, + fontsize=fs['lab_tex'], rotation=0, ha='left', va='center', ) -ylab_analysis_kwargs = dict( - x=0.02, - fontsize=16, +ylab_big_kwargs = dict( + x=0, + fontsize=fs['lab_tex'], ha='center', va='top', ) +yloc = dict( + env=1000, + log=40, + inv=20 +) +title_kwargs = dict( + x=0.5, + yref=1, + ha='center', + va='top', + fontsize=fs['tit_norm'], +) letter_snip_kwargs = dict( - x=0.02, - y=0.97, + x=0, + y=1, ha='left', va='top', - fontsize=22, + fontsize=fs['letter'], ) -letter_analysis_kwargs = dict( +letter_big_kwargs = dict( x=0, yref=letter_snip_kwargs['y'], ha='left', va='top', - fontsize=22, + fontsize=fs['letter'], +) +zoom_inset_bounds = [0.1, 0.2, 0.8, 0.6] +zoom_kwargs = dict( + x0=0.45, + x1=0.55, + y0=0, + y1=0.0006, + low_left=True, + low_right=True, + ec='k', + lw=1, + alpha=1, ) bar_time = 5 bar_kwargs = dict( - y0=0.5, - y1=0.6, + y0=-0.2, + y1=-0.05, color='k', - lw = 0, + lw=0, + clip_on=False, +) +diag_kwargs = dict( + c=(0.75, 0.75, 0.75), + lw=2, + ls='--', + zorder=1.9, ) # EXECUTION: @@ -153,91 +186,116 @@ for data_path in data_paths: # Load invariance data: pure_data, config = load_data(data_path, **load_kwargs) noise_data, _ = load_data(data_path.replace('.npz', '_noise.npz'), **load_kwargs) - t_full = np.arange(pure_data['env'].shape[0]) / config['env_rate'] + pure_scales, noise_scales = pure_data['scales'], noise_data['scales'] + t_full = np.arange(pure_data['snip_env'].shape[0]) / config['env_rate'] # Prepare overall graph: fig = plt.figure(**fig_kwargs) super_grid = fig.add_gridspec(**super_grid_kwargs) # Prepare pure-song snippet axes: + snip_grid_kwargs['ncols'] = pure_data['example_scales'].size pure_subfig = fig.add_subfigure(super_grid[subfig_specs['pure']]) - pure_grid_kwargs['nrows' if pure_grid_kwargs['nrows'] is None else 'ncols'] = pure_data['example_scales'].size - pure_axes = add_snip_axes(pure_subfig, pure_grid_kwargs) + pure_axes = add_snip_axes(pure_subfig, snip_grid_kwargs) for ax, stage in zip(pure_axes[:, 0], stages): + ax.yaxis.set_major_locator(plt.MultipleLocator(yloc[stage])) ylabel(ax, ylabels[stage], **ylab_snip_kwargs, transform=pure_subfig.transSubfigure) - for ax, scale in zip(pure_axes[snip_specs['env']], pure_data['example_scales']): - ax.set_title(f'$\\alpha={strip_zeros(scale)}$') + for ax, scale in zip(pure_axes[0, :], pure_data['example_scales']): + title_subplot(ax, f'$\\alpha={strip_zeros(scale)}$', ref=pure_subfig, **title_kwargs) + pure_inset = pure_axes[0, 0].inset_axes(zoom_inset_bounds) + pure_inset.spines[:].set(visible=True, lw=zoom_kwargs['lw']) + hide_ticks(pure_inset, 'bottom', ticks=False) + hide_ticks(pure_inset, 'left', ticks=False) # Prepare noise-song snippet axes: + snip_grid_kwargs['ncols'] = noise_data['example_scales'].size noise_subfig = fig.add_subfigure(super_grid[subfig_specs['noise']]) - noise_grid_kwargs['nrows' if noise_grid_kwargs['nrows'] is None else 'ncols'] = noise_data['example_scales'].size - noise_grid = noise_subfig.add_gridspec(**noise_grid_kwargs) - noise_axes = add_snip_axes(noise_subfig, noise_grid_kwargs) + noise_axes = add_snip_axes(noise_subfig, snip_grid_kwargs) for ax, stage in zip(noise_axes[:, 0], stages): + ax.yaxis.set_major_locator(plt.MultipleLocator(yloc[stage])) ylabel(ax, ylabels[stage], **ylab_snip_kwargs, transform=noise_subfig.transSubfigure) - for ax, scale in zip(noise_axes[snip_specs['env']], noise_data['example_scales']): - ax.set_title(f'$\\alpha={strip_zeros(scale)}$') - letter_subplots([pure_subfig, noise_subfig], **letter_snip_kwargs) + for ax, scale in zip(noise_axes[0, :], noise_data['example_scales']): + title_subplot(ax, f'$\\alpha={strip_zeros(scale)}$', ref=noise_subfig, **title_kwargs) + letter_subplots([pure_subfig, noise_subfig], 'ac', **letter_snip_kwargs) + noise_inset = noise_axes[0, 0].inset_axes(zoom_inset_bounds) + noise_inset.spines[:].set(visible=True, lw=zoom_kwargs['lw']) + hide_ticks(noise_inset, 'bottom', ticks=False) + hide_ticks(noise_inset, 'left', ticks=False) - # Prepare analysis axis: - analysis_subfig = fig.add_subfigure(super_grid[subfig_specs['analysis']]) - analysis_grid = analysis_subfig.add_gridspec(**analysis_grid_kwargs) - analysis_ax = analysis_subfig.add_subplot(analysis_grid[0, 0]) - analysis_ax.set_xlim(noise_data['scales'].min(), noise_data['scales'].max()) - analysis_ax.set_xscale('symlog', linthresh=pure_data['scales'][1], linscale=0.5) - xlabel(analysis_ax, xlabels['analysis'], **xlab_analysis_kwargs, - transform=analysis_subfig.transSubfigure) - analysis_ax.set_yscale('log') - ylabel(analysis_ax, ylabels['analysis'], **ylab_analysis_kwargs, - transform=analysis_subfig.transSubfigure) - letter_subplot(analysis_subfig, 'c', **letter_analysis_kwargs, ref=pure_subfig) + # Prepare analysis axes: + big_subfig = fig.add_subfigure(super_grid[subfig_specs['big']]) + big_grid = big_subfig.add_gridspec(**big_grid_kwargs) + big_axes = np.zeros((big_grid.nrows,), dtype=object) + for i, scales in enumerate([pure_scales, noise_scales]): + ax = big_subfig.add_subplot(big_grid[i, 0]) + ax.set_xlim(scales[0], scales[-1]) + ax.set_ylim(scales[0], scales[-1]) + 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(big_subfig, 'b', ref=pure_subfig, **letter_big_kwargs) + else: + xlabel(ax, xlabels['big'], transform=big_subfig.transSubfigure, **xlab_big_kwargs) + letter_subplot(big_subfig, 'd', ref=noise_subfig, **letter_big_kwargs) + big_axes[i] = ax # Plot pure-song envelope snippets: - plot_snippets(pure_axes[snip_specs['env']], t_full, pure_data['env'], - ymin=0, c=colors['env'], lw=lw_snippets) - + handle = plot_snippets(pure_axes[0, :], t_full, pure_data['snip_env'], + ymin=0, c=colors['env'], lw=lw_snippets)[0] + zoom_inset(pure_axes[0, 0], pure_inset, handle, transform=pure_axes[0, 0].transAxes, **zoom_kwargs) + # Plot pure-song logarithmic snippets: - plot_snippets(pure_axes[snip_specs['log']], t_full, pure_data['log'], - ymax=None, c=colors['log'], lw=lw_snippets) + plot_snippets(pure_axes[1, :], t_full, pure_data['snip_log'], + c=colors['log'], lw=lw_snippets) # Plot pure-song invariant snippets: - plot_snippets(pure_axes[snip_specs['inv']], t_full, pure_data['inv'], + plot_snippets(pure_axes[2, :], t_full, pure_data['snip_inv'], c=colors['inv'], lw=lw_snippets) - # Indicate time scale: - time_bar(pure_axes[snip_specs['env']][0], bar_time, **bar_kwargs) - # Plot noise-song envelope snippets: - plot_snippets(noise_axes[snip_specs['env']], t_full, noise_data['env'], - ymin=0, c=colors['env'], lw=lw_snippets) + handle = plot_snippets(noise_axes[0, :], t_full, noise_data['snip_env'], + ymin=0, c=colors['env'], lw=lw_snippets)[0] + zoom_inset(noise_axes[0, 0], noise_inset, handle, transform=noise_axes[0, 0].transAxes, **zoom_kwargs) # Plot noise-song logarithmic snippets: - plot_snippets(noise_axes[snip_specs['log']], t_full, noise_data['log'], - ymax=None, c=colors['log'], lw=lw_snippets) + plot_snippets(noise_axes[1, :], t_full, noise_data['snip_log'], + c=colors['log'], lw=lw_snippets) # Plot noise-song invariant snippets: - plot_snippets(noise_axes[snip_specs['inv']], t_full, noise_data['inv'], + plot_snippets(noise_axes[2, :], t_full, noise_data['snip_inv'], c=colors['inv'], lw=lw_snippets) # Indicate time scale: - time_bar(noise_axes[snip_specs['env']][0], bar_time, **bar_kwargs) + time_bar(noise_axes[2, -1], bar_time, **bar_kwargs) - # Plot pure-song SD ratios (ideal): - base_ind = np.argmin(pure_data['scales']) - measure_inv = pure_data['measure_inv'] / pure_data['measure_inv'][base_ind] - analysis_ax.plot(pure_data['scales'], measure_inv, c=colors['inv'], lw=lw_analysis, ls='--') + if compute_ratios: + # Relate pure-song measures to zero scale: + pure_data['measure_env'] /= ref_measures['env'] + pure_data['measure_log'] /= ref_measures['log'] + pure_data['measure_inv'] /= ref_measures['inv'] + # Relate noise-song measures to zero scale: + noise_data['measure_env'] /= ref_measures['env'] + noise_data['measure_log'] /= ref_measures['log'] + noise_data['measure_inv'] /= ref_measures['inv'] - # Plot noise-song SD ratios (limited): - base_ind = np.argmin(noise_data['scales']) - measure_env = noise_data['measure_env'] / noise_data['measure_env'][base_ind] - measure_log = noise_data['measure_log'] / noise_data['measure_log'][base_ind] - measure_inv = noise_data['measure_inv'] / noise_data['measure_inv'][base_ind] - analysis_ax.plot(noise_data['scales'], measure_env, c=colors['env'], lw=lw_analysis) - analysis_ax.plot(noise_data['scales'], measure_log, c=colors['log'], lw=lw_analysis) - analysis_ax.plot(noise_data['scales'], measure_inv, c=colors['inv'], lw=lw_analysis) - analysis_ax.set_ylim(0.9, measure_env.max()) + # Plot pure-song measures (ideal): + big_axes[0].plot(pure_scales, pure_data['measure_env'], c=colors['env'], lw=lw_big) + big_axes[0].plot(pure_scales, pure_data['measure_log'], c=colors['log'], lw=lw_big) + big_axes[0].plot(pure_scales, pure_data['measure_inv'], c=colors['inv'], lw=lw_big) + + # Plot noise-song measures (limited): + big_axes[1].plot(noise_scales, noise_data['measure_env'], c=colors['env'], lw=lw_big) + 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) + + # Indicate diagonal: + big_axes[0].plot(pure_scales, pure_scales, **diag_kwargs) + big_axes[1].plot(noise_scales, noise_scales, **diag_kwargs) if save_path is not None: fig.savefig(save_path) diff --git a/python/fig_invariance_thresh-lp_single.py b/python/fig_invariance_thresh-lp_single.py index 2d45643..3849f5a 100644 --- a/python/fig_invariance_thresh-lp_single.py +++ b/python/fig_invariance_thresh-lp_single.py @@ -6,17 +6,18 @@ from thunderhopper.filetools import search_files from thunderhopper.modeltools import load_data from thunderhopper.filtertools import find_kern_specs from color_functions import load_colors, shade_colors -from plot_functions import hide_axis, ylimits, xlabel, ylabel, super_ylabel,\ +from plot_functions import hide_axis, ylimits, xlabel, ylabel, super_ylabel, super_xlabel,\ plot_line, plot_barcode, strip_zeros, time_bar,\ - letter_subplot, letter_subplots + letter_subplot, letter_subplots, title_subplot from IPython import embed -def add_snip_axes(fig, grid_kwargs): +def add_snip_axes(fig, grid_kwargs, snip_specs): grid = fig.add_gridspec(**grid_kwargs) - axes = np.zeros((grid.nrows, grid.ncols), dtype=object) - for i, j in product(range(grid.nrows), range(grid.ncols)): - axes[i, j] = fig.add_subplot(grid[i, j]) - [hide_axis(ax, 'left') for ax in axes.flatten()] + axes = np.zeros((len(snip_specs), grid.ncols), dtype=object) + for i, specs in enumerate(snip_specs.values()): + for j in range(grid.ncols): + axes[i, j] = fig.add_subplot(grid[specs, j]) + [hide_axis(ax, 'left') for ax in axes[:, 1:].flatten()] [hide_axis(ax, 'bottom') for ax in axes.flatten()] return axes @@ -88,14 +89,14 @@ subfig_specs = dict( big=(slice(None), -1), ) snip_grid_kwargs = dict( - nrows=len(stages), + nrows=len(stages) + 1, ncols=None, wspace=0.3, - hspace=0.1, - left=0.1, + hspace=0, + left=0.17, right=0.93, - bottom=0.05, - top=0.85 + bottom=0.15, + top=0.9 ) big_grid_kwargs = dict( nrows=1, @@ -107,6 +108,11 @@ big_grid_kwargs = dict( bottom=0.1, top=0.99 ) +snip_specs = dict( + conv=slice(0, -2), + bi=-2, + feat=-1 +) inset_bounds = [1.02, 0, 0.2, 1] # PLOT SETTINGS: @@ -119,20 +125,27 @@ lw = dict( big=4, ) xlabels = dict( + snip='time [s]', big='scale $\\alpha$', ) -xlab_big_kwargs = dict( - y=0.01, - fontsize=16, - ha='center', - va='bottom', -) ylabels = dict( conv='$c_i$', bi='$b_i$', feat='$f_i$', big='$\\mu_f$', ) +xlab_snip_kwargs = dict( + y=0, + fontsize=16, + ha='center', + va='bottom', +) +xlab_big_kwargs = dict( + y=0, + fontsize=16, + ha='center', + va='bottom', +) ylab_snip_kwargs = dict( x=0.08, fontsize=20, @@ -141,7 +154,7 @@ ylab_snip_kwargs = dict( va='center', ) ylab_super_kwargs = dict( - x=0.005, + x=0, fontsize=16, ha='left', va='center', @@ -153,11 +166,21 @@ ylab_big_kwargs = dict( va='top', ) yloc = dict( + conv=100, + bi=1, + feat=1, big=0.2, ) +title_kwargs = dict( + x=0.5, + yref=1, + ha='center', + va='top', + fontsize=16, +) letter_snip_kwargs = dict( - x=0.01, - y=0.9, + x=0, + y=1, ha='left', va='top', fontsize=22, @@ -178,7 +201,7 @@ dist_fill_kwargs = dict( color=colors['bi'], lw=0.1, ) -bar_time = 0.5 +bar_time = 0.1 bar_kwargs = dict( y0=0.3, y1=0.4, @@ -190,7 +213,7 @@ kernel = np.array([ [2, 0.004], [3, 0.002], ])[np.array([1])] -zoom_rel = np.array([0.5, 0.525]) +zoom_rel = np.array([0.5, 0.515]) # EXECUTION: @@ -232,17 +255,22 @@ for data_path in data_paths: for i in range(data['threshs'].size): subfig_specs['snip'] = (i, subfig_specs['snip'][1]) snip_subfig = fig.add_subfigure(super_grid[subfig_specs['snip']]) - axes = add_snip_axes(snip_subfig, snip_grid_kwargs) + axes = add_snip_axes(snip_subfig, snip_grid_kwargs, snip_specs) snip_axes[snip_subfig] = axes super_ylabel(f'{strip_zeros(100 * data["thresh_perc"][i])}%', snip_subfig, axes[-1, 0], axes[0, 0], **ylab_super_kwargs) for ax, stage in zip(axes[:, 0], stages): + ax.yaxis.set_major_locator(plt.MultipleLocator(yloc[stage])) ylabel(ax, ylabels[stage], **ylab_snip_kwargs, transform=snip_subfig.transSubfigure) if i == 0: + axes[0, 0].set_xlim(t_full[0], t_full[-1]) time_bar(axes[0, 0], bar_time, **bar_kwargs) for ax, scale in zip(axes[0, :], data['example_scales']): - ax.set_title(f'$\\alpha={strip_zeros(scale)}$') + title = f'$\\alpha={strip_zeros(scale)}$' + title_subplot(ax, title, **title_kwargs, ref=fig) + elif i == data['threshs'].size - 1: + super_xlabel(xlabels['snip'], snip_subfig, axes[-1, 0], axes[-1, -1], **xlab_snip_kwargs) letter_subplots(snip_axes.keys(), **letter_snip_kwargs) # Prepare analysis axis: diff --git a/python/fig_invariance_thresh-lp_species.py b/python/fig_invariance_thresh-lp_species.py index 5c047da..dd0e4d6 100644 --- a/python/fig_invariance_thresh-lp_species.py +++ b/python/fig_invariance_thresh-lp_species.py @@ -213,38 +213,45 @@ lw = dict( space_kwargs = dict( s=30, ) -xlabs = dict( +xlabels = dict( spec='scale $\\alpha$', big='$\\mu_{f_1}$' ) -ylabs = dict( +ylabels = dict( spec='$\\mu_f$', big='$\\mu_{f_2}$', + bar='scale $\\alpha$', ) xlab_spec_kwargs = dict( - y=0.005, + y=0, fontsize=16, ha='center', va='bottom', ) +xlab_big_kwargs = dict( + y=0, + fontsize=20, + ha='center', + va='bottom', +) ylab_spec_kwargs = dict( x=0, fontsize=20, ha='left', va='center', ) -xlab_big_kwargs = dict( - y=0.005, - fontsize=20, - ha='center', - va='bottom', -) ylab_big_kwargs = dict( x=0.03, fontsize=20, ha='center', va='center', ) +ylab_cbar_kwargs = dict( + x=1, + fontsize=16, + ha='center', + va='bottom', +) xloc = dict( big=0.5, ) @@ -252,18 +259,18 @@ yloc = dict( spec=0.5, big=0.5 ) -spec_letter_kwargs = dict( +letter_spec_kwargs = dict( x=0, - y=1.03, + yref=1, ha='center', - va='bottom', + va='top', fontsize=22, ) -big_letter_kwargs = dict( +letter_big_kwargs = dict( x=0, - yref=spec_letter_kwargs['y'], + yref=1, ha='center', - va='bottom', + va='top', fontsize=22, ) time_bar_kwargs = dict( @@ -274,7 +281,7 @@ time_bar_kwargs = dict( lw=0 ) cbar_bounds = [ - 0.8, + 0.05, big_grid_kwargs['bottom'], 0.15, big_grid_kwargs['top'] - big_grid_kwargs['bottom'] @@ -297,11 +304,11 @@ for i, j in product(range(spec_grid_kwargs['nrows']), range(n_species)): ax.yaxis.set_major_locator(plt.MultipleLocator(yloc['spec'])) ax.set_ylim(0, 1) spec_axes[i, j] = ax -super_xlabel(xlabs['spec'], spec_subfig, spec_axes[-1, 0], spec_axes[-1, -1], **xlab_spec_kwargs) -super_ylabel(ylabs['spec'], spec_subfig, spec_axes[-1, 0], spec_axes[0, 0], **ylab_spec_kwargs) +super_xlabel(xlabels['spec'], spec_subfig, spec_axes[-1, 0], spec_axes[-1, -1], **xlab_spec_kwargs) +super_ylabel(ylabels['spec'], spec_subfig, spec_axes[-1, 0], spec_axes[0, 0], **ylab_spec_kwargs) [hide_ticks(ax, side='bottom') for ax in spec_axes[0, :]] [hide_ticks(ax, side='left') for ax in spec_axes[:, 1:].ravel()] -letter_subplots(spec_axes[0, :], labels='abc', **spec_letter_kwargs) +letter_subplots(spec_axes[0, :], labels='abc', ref=spec_subfig, **letter_spec_kwargs) # Prepare kernel insets: x0 = np.linspace(0, 1, kernels.shape[0] + 1)[:-1] + 1 / kernels.shape[0] / 2 @@ -325,23 +332,17 @@ for i in range(big_axes.size): ax.xaxis.set_major_locator(plt.MultipleLocator(xloc['big'])) ax.yaxis.set_major_locator(plt.MultipleLocator(yloc['big'])) ax.set_aspect(**anchor_kwargs) - # ax.set_ylabel(ylabs['big'], **ylab_big_kwargs) - ylabel(ax, ylabs['big'], transform=big_subfig.transSubfigure, **ylab_big_kwargs) + # ax.set_ylabel(ylabels['big'], **ylab_big_kwargs) + ylabel(ax, ylabels['big'], transform=big_subfig.transSubfigure, **ylab_big_kwargs) big_axes[i] = ax -super_xlabel(xlabs['big'], big_subfig, big_axes[1], big_axes[1], **xlab_big_kwargs) +super_xlabel(xlabels['big'], big_subfig, big_axes[1], big_axes[1], **xlab_big_kwargs) hide_ticks(big_axes[0], side='bottom') -letter_subplot(big_axes[0], 'd', ref=spec_axes[0, 0], **big_letter_kwargs) +letter_subplot(big_axes[0], 'd', ref=big_subfig, **letter_big_kwargs) # Prepare colorbars: -bar_ax = big_subfig.add_axes(cbar_bounds) -bar_axes = split_subplot(bar_ax, side=['right', 'right'], size=100, pad=0) -bar_axes = [bar_ax] + bar_axes -for ax in bar_axes: - ax.spines[['right', 'top']].set_visible(True) - hide_ticks(ax, 'bottom', ticks=False) - hide_ticks(ax, 'left', ticks=False) -bar_axes[-1].tick_params(axis='y', which='both', right=True, labelright=True) -# plt.show() +cbar_bounds[0] += big_axes[-1].get_position().x1 +bar_axes = [big_subfig.add_axes(cbar_bounds)] +bar_axes.extend(split_subplot(bar_axes[0], side=['right', 'right'], size=100, pad=0)) # Plot results per species: for i, pure_path in enumerate(pure_paths): @@ -377,10 +378,6 @@ for i, pure_path in enumerate(pure_paths): inset.set_ylim(ylims) time_bar(insets[0], parent=spec_axes[0, 0], **time_bar_kwargs) - # Prepare shaded colors: - # factors = np.linspace(*shade_factors, scales.size) - # shaded_colors = shade_colors(spec_colors[i], factors) - # Plot pure feature space: handle = big_axes[0].scatter(pure_measure[:, 0], pure_measure[:, 1], c=scales, cmap=spec_cmaps[i], **space_kwargs) @@ -391,6 +388,11 @@ for i, pure_path in enumerate(pure_paths): # Indicate scale color code: big_subfig.colorbar(handle, cax=bar_axes[i]) + bar_axes[i].set_yscale('symlog', linthresh=scales[1], linscale=0.2) + if i < len(pure_paths) - 1: + hide_ticks(bar_axes[i], 'right', ticks=False) + else: + ylabel(bar_axes[i], ylabels['bar'], transform=big_subfig.transSubfigure, **ylab_cbar_kwargs) if save_path is not None: fig.savefig(save_path) diff --git a/python/fig_pathway_stages.py b/python/fig_pathway_stages.py index fc6a5ba..1940652 100644 --- a/python/fig_pathway_stages.py +++ b/python/fig_pathway_stages.py @@ -4,7 +4,7 @@ import numpy as np import matplotlib.pyplot as plt from thunderhopper.modeltools import load_data from color_functions import load_colors -from plot_functions import prepare_fig, hide_axis, letter_subplots,\ +from plot_functions import hide_axis, letter_subplots,\ ylabel, super_xlabel, plot_line, plot_barcode,\ indicate_zoom, assign_colors, reorder_traces from IPython import embed @@ -15,33 +15,28 @@ data_paths = glob.glob(f'../data/processed/{target}*.npz') stages = ['filt', 'env', 'log', 'inv', 'conv', 'bi', 'feat'] save_path = '../figures/' -# PLOT SETTINGS: +# GRAPH SETTINGS: fig_kwargs = dict( - width=32, - height=12, + figsize=(32/2.54, 16/2.54), + sharex='col', + subplot_kw=dict( + facecolor='none' + ), + gridspec_kw=dict( + wspace=0.15, + hspace=0.3, + left=0.1, + right=0.99, + bottom=0.08, + top=0.95 + ), ) -grid_kwargs = dict( - wspace=0.15, - hspace=0.3, - left=0.1, - right=0.99, - bottom=0.1, - top=0.95 -) -ylabels = dict( - filt=r'$x_{\text{filt}}$', - env=r'$x_{\text{env}}$', - log=r'$x_{\text{dB}}$', - inv=r'$x_{\text{adapt}}$', - conv=r'$c_i$', - bi=r'$b_i$', - feat=r'$f_i$' -) -ylab_kwargs = dict( - x=-0.23, - rotation=0, - ha='left', - va='center', + +# PLOT SETTINGS: +fs = dict( + lab_tex=20, + lab_norm=16, + letter=22 ) colors = load_colors('../data/stage_colors.npz') lw_full = dict( @@ -62,22 +57,58 @@ lw_zoom = dict( bi=0.2, feat=1.5 ) -loc_full = dict( +xlabels = dict( + super='time [s]', +) +ylabels = dict( + filt=r'$x_{\text{filt}}$', + env=r'$x_{\text{env}}$', + log=r'$x_{\text{dB}}$', + inv=r'$x_{\text{adapt}}$', + conv=r'$c_i$', + bi=r'$b_i$', + feat=r'$f_i$' +) +xlab_kwargs = dict( + y=0, + ha='center', + va='bottom', + fontsize=fs['lab_norm'], +) +ylab_kwargs = dict( + x=0, + rotation=0, + ha='left', + va='center', + fontsize=fs['lab_tex'], +) +xloc = dict( + full=2, + zoom=0.2 +) +yloc_full = dict( filt=0.2, env=0.1, - log=20, - inv=10, - conv=1, + log=40, + inv=20, + conv=2, feat=1 ) -loc_zoom = dict( +yloc_zoom = dict( filt=0.1, env=0.02, - log=20, - inv=10, - conv=0.2, + log=40, + inv=20, + conv=0.5, feat=1 ) +letter_kwargs = dict( + x=0, + y=1, + ha='left', + va='bottom', + fontsize=fs['letter'], +) zoom_rel = np.array([0.3, 0.4]) zoom_kwargs = dict( color=3 * (0.85,), @@ -130,61 +161,62 @@ for data_path in data_paths: # PART I: PREPROCESSING STAGE - fig, axes = prepare_fig(4, 2, **fig_kwargs, **grid_kwargs) - super_xlabel('time [s]', fig, axes[0, 0], axes[0, -1]) + fig, axes = plt.subplots(4, 2, **fig_kwargs) + super_xlabel(xlabels['super'], fig, axes[0, 0], axes[0, -1], **xlab_kwargs) + [hide_axis(ax, 'bottom') for ax in axes[:-1, :].ravel()] # Bandpass-filtered signal: ax_full, ax_zoom = axes[0, :] - ylabel(ax_full, ylabels['filt'], **ylab_kwargs) - plot_line(ax_full, t_full, data['filt'], c=colors['filt'], lw=lw_full['filt'], yloc=loc_full['filt']) - plot_line(ax_zoom, t_zoom, data['filt'][zoom_mask], c=colors['filt'], lw=lw_zoom['filt'], yloc=loc_zoom['filt']) - hide_axis(ax_full, 'bottom') - hide_axis(ax_zoom, 'bottom') + ylabel(ax_full, ylabels['filt'], transform=fig.transFigure, **ylab_kwargs) + plot_line(ax_full, t_full, data['filt'], c=colors['filt'], lw=lw_full['filt'], yloc=yloc_full['filt']) + plot_line(ax_zoom, t_zoom, data['filt'][zoom_mask], c=colors['filt'], lw=lw_zoom['filt'], yloc=yloc_zoom['filt']) # Signal envelope: ax_full, ax_zoom = axes[1, :] - ylabel(ax_full, ylabels['env'], **ylab_kwargs) - plot_line(ax_full, t_full, data['env'], ymin=0, c=colors['env'], lw=lw_full['env'], yloc=loc_full['env']) - plot_line(ax_zoom, t_zoom, data['env'][zoom_mask], ymin=0, c=colors['env'], lw=lw_zoom['env'], yloc=loc_zoom['env']) - hide_axis(ax_full, 'bottom') - hide_axis(ax_zoom, 'bottom') + ylabel(ax_full, ylabels['env'], transform=fig.transFigure, **ylab_kwargs) + plot_line(ax_full, t_full, data['env'], ymin=0, c=colors['env'], lw=lw_full['env'], yloc=yloc_full['env']) + plot_line(ax_zoom, t_zoom, data['env'][zoom_mask], ymin=0, c=colors['env'], lw=lw_zoom['env'], yloc=yloc_zoom['env']) # Logarithmic envelope: ax_full, ax_zoom = axes[2, :] - ylabel(ax_full, ylabels['log'], **ylab_kwargs) - plot_line(ax_full, t_full, data['log'], ymax=0, c=colors['log'], lw=lw_full['log'], yloc=loc_full['log']) - plot_line(ax_zoom, t_zoom, data['log'][zoom_mask], ymax=0, c=colors['log'], lw=lw_zoom['log'], yloc=loc_zoom['log']) - hide_axis(ax_full, 'bottom') - hide_axis(ax_zoom, 'bottom') + ylabel(ax_full, ylabels['log'], transform=fig.transFigure, **ylab_kwargs) + plot_line(ax_full, t_full, data['log'], ymax=0, c=colors['log'], lw=lw_full['log'], yloc=yloc_full['log']) + plot_line(ax_zoom, t_zoom, data['log'][zoom_mask], ymax=0, c=colors['log'], lw=lw_zoom['log'], yloc=yloc_zoom['log']) # Adapted envelope: ax_full, ax_zoom = axes[3, :] - ylabel(ax_full, ylabels['inv'], **ylab_kwargs) - plot_line(ax_full, t_full, data['inv'], c=colors['inv'], lw=lw_full['inv'], yloc=loc_full['inv']) - plot_line(ax_zoom, t_zoom, data['inv'][zoom_mask], c=colors['inv'], lw=lw_zoom['inv'], yloc=loc_zoom['inv']) + ylabel(ax_full, ylabels['inv'], transform=fig.transFigure, **ylab_kwargs) + plot_line(ax_full, t_full, data['inv'], c=colors['inv'], lw=lw_full['inv'], yloc=yloc_full['inv']) + plot_line(ax_zoom, t_zoom, data['inv'][zoom_mask], c=colors['inv'], lw=lw_zoom['inv'], yloc=yloc_zoom['inv']) # Posthoc adjustments: ax_full.set_xlim(t_full[0], t_full[-1]) + ax_full.xaxis.set_major_locator(plt.MultipleLocator(xloc['full'])) ax_zoom.set_xlim(t_zoom[0], t_zoom[-1]) + ax_zoom.xaxis.set_major_locator(plt.MultipleLocator(xloc['zoom'])) indicate_zoom(fig, axes[0, 0], axes[-1, 0], zoom_abs, **zoom_kwargs) indicate_zoom(fig, axes[0, 1], axes[-1, 1], zoom_abs, **zoom_kwargs) - letter_subplots(axes[:, 0]) + letter_subplots(axes[:, 0], **letter_kwargs) if save_path is not None: fig.savefig(f'{save_path}fig_pre_stages.pdf') + # Update parameters: + fig_kwargs['gridspec_kw'].update( + left=0.06, + ) # PART II: FEATURE EXTRACTION STAGE: - fig, axes = prepare_fig(3, 2, **fig_kwargs, **grid_kwargs) - super_xlabel('time [s]', fig, axes[0, 0], axes[0, -1]) + fig, axes = plt.subplots(3, 2, **fig_kwargs) + super_xlabel(xlabels['super'], fig, axes[0, 0], axes[0, -1], **xlab_kwargs) # Convolutional filter responses: ax_full, ax_zoom = axes[0, :] - ylabel(ax_full, ylabels['conv'], **ylab_kwargs) + ylabel(ax_full, ylabels['conv'], transform=fig.transFigure, **ylab_kwargs) signal = data['conv'][:, kern_inds] - handles = plot_line(ax_full, t_full, signal, lw=lw_full['conv'], yloc=loc_full['conv']) + 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) - handles = plot_line(ax_zoom, t_zoom, signal[zoom_mask, :], lw=lw_zoom['conv'], yloc=loc_zoom['conv']) + 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, :]) hide_axis(ax_full, 'bottom') @@ -192,7 +224,7 @@ for data_path in data_paths: # Binary responses: ax_full, ax_zoom = axes[1, :] - ylabel(ax_full, ylabels['bi'], **ylab_kwargs) + ylabel(ax_full, ylabels['bi'], transform=fig.transFigure, **ylab_kwargs) signal = data['bi'][:, kern_inds] handles = plot_barcode(ax_full, t_full, signal, lw=lw_full['bi']) assign_colors(handles, kern_specs[:, 0], bi_colors) @@ -201,19 +233,21 @@ for data_path in data_paths: # Finalized features: ax_full, ax_zoom = axes[2, :] - ylabel(ax_full, ylabels['feat'], **ylab_kwargs) + ylabel(ax_full, ylabels['feat'], transform=fig.transFigure, **ylab_kwargs) signal = data['feat'][:, kern_inds] - handles = plot_line(ax_full, t_full, signal, ymin=0, ymax=1, c=colors['feat'], lw=lw_full['feat'], yloc=loc_full['feat']) + handles = plot_line(ax_full, t_full, signal, ymin=0, ymax=1, c=colors['feat'], lw=lw_full['feat'], yloc=yloc_full['feat']) assign_colors(handles, kern_specs[:, 0], feat_colors) - handles = plot_line(ax_zoom, t_zoom, signal[zoom_mask, :], ymin=0, ymax=1, c=colors['feat'], lw=lw_zoom['feat'], yloc=loc_zoom['feat']) + handles = plot_line(ax_zoom, t_zoom, signal[zoom_mask, :], ymin=0, ymax=1, c=colors['feat'], lw=lw_zoom['feat'], yloc=yloc_zoom['feat']) assign_colors(handles, kern_specs[:, 0], feat_colors) # Posthoc adjustments: ax_full.set_xlim(t_full[0], t_full[-1]) + ax_full.xaxis.set_major_locator(plt.MultipleLocator(xloc['full'])) ax_zoom.set_xlim(t_zoom[0], t_zoom[-1]) + ax_zoom.xaxis.set_major_locator(plt.MultipleLocator(xloc['zoom'])) indicate_zoom(fig, axes[0, 0], axes[-1, 0], zoom_abs, **zoom_kwargs) indicate_zoom(fig, axes[0, 1], axes[-1, 1], zoom_abs, **zoom_kwargs) - letter_subplots(axes[:, 0]) + letter_subplots(axes[:, 0], **letter_kwargs) if save_path is not None: fig.savefig(f'{save_path}fig_feat_stages.pdf') plt.show() diff --git a/python/plot_functions.py b/python/plot_functions.py index aba8692..56b8bb0 100644 --- a/python/plot_functions.py +++ b/python/plot_functions.py @@ -2,21 +2,6 @@ import string import numpy as np import matplotlib.pyplot as plt from matplotlib.transforms import BboxTransformTo -from itertools import product - -def prepare_fig(nrows, ncols, width=8, height=None, rheight=2, unit=1/2.54, - 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 * unit, height * unit)) - 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 hide_ticks(ax, side='bottom', ticks=True): axis = 'x' if side in ['top', 'bottom'] else 'y' @@ -31,6 +16,20 @@ def hide_axis(ax, side='bottom'): which='both', **params) return None +def title_subplot(artist, title, x=0.5, y=1.0, xref=None, yref=None, ref=None, + ha='center', va='bottom', fontsize=16, fontweight='normal', **kwargs): + + trans_artist = BboxTransformTo(artist.bbox) + if xref is not None or yref is not None: + transform = BboxTransformTo(ref.bbox) + trans_artist.inverted() + if xref is not None: + x = transform.transform((xref, 0))[0] + if yref is not None: + y = transform.transform((0, yref))[1] + artist.text(x, y, title, transform=trans_artist, ha=ha, va=va, + fontsize=fontsize, fontweight=fontweight, **kwargs) + return None + def letter_subplot(artist, label, x=None, y=None, xref=None, yref=None, ref=None, ha='left', va='bottom', fontsize=16, fontweight='bold', **kwargs): trans_artist = BboxTransformTo(artist.bbox) @@ -141,6 +140,8 @@ def plot_line(ax, time, signal, ymin=None, ymax=None, xmin=None, xmax=None, return handles def plot_barcode(ax, time, binary, offset=0.5, xmin=None, xmax=None, **kwargs): + if binary.ndim == 1: + binary = binary[:, None] lower, upper, handles = 0, 1, [] for i in range(binary.shape[1]): h = ax.fill_between(time, lower, upper, where=binary[:, i], **kwargs) @@ -186,21 +187,63 @@ def strip_zeros(num, right_digits=5): return f'{left}.{right}' return left -def time_bar(ax, dur, y0=0.9, y1=0.95, xshift=0.5, parent=None, transform=None, **kwargs): - t_lims = ax.get_xlim() - span = t_lims[1] - t_lims[0] - if parent is not None or transform is not None: - if transform is None: - transform = BboxTransformTo(parent.bbox) - kwargs['transform'] = transform - transform = ax.transData + transform.inverted() - x0 = transform.transform((t_lims[0], 0))[0] - x1 = transform.transform((t_lims[0] + dur, 0))[0] - dur = x1 - x0 - span = 1 - elif parent is None: +def time_bar(ax, dur, y0=0.9, y1=0.95, xshift=0.5, parent=None, **kwargs): + if parent is None: parent = ax - x0 = (span - dur) * xshift - x1 = x0 + dur + trans_parent = BboxTransformTo(parent.bbox) + kwargs['transform'] = trans_parent + transform = ax.transData + trans_parent.inverted() + t0 = ax.get_xlim()[0] + x0 = transform.transform((t0, 0))[0] + x1 = transform.transform((t0 + dur, 0))[0] + dur = x1 - x0 + x0 = (1 - dur) * xshift parent.add_artist(plt.Rectangle((x0, y0), dur, y1 - y0, **kwargs)) return None + +def zoom_inset(ax, inset, handle, x0=None, x1=None, y0=None, y1=None, ref='x', + transform = None, + low_left=False, up_left=False, low_right=False, up_right=False, + props=['c', 'lw', 'ls', 'zorder', 'alpha'], **kwargs): + if not kwargs: + kwargs = dict(edgecolor='k', alpha=1, lw=2) + + if transform is not None: + transform = transform + ax.transData.inverted() + xlims = ax.get_xlim() + ylims = ax.get_ylim() + if x0 is None: + x0 = xlims[0] + elif transform is not None: + x0 = transform.transform((x0, 0))[0] + if x1 is None: + x1 = xlims[1] + elif transform is not None: + x1 = transform.transform((x1, 0))[0] + if y0 is None: + y0 = ylims[0] + elif transform is not None: + y0 = transform.transform((0, y0))[1] + if y1 is None: + y1 = ylims[1] + elif transform is not None: + y1 = transform.transform((0, y1))[1] + inset.set_xlim(x0, x1) + inset.set_ylim(y0, y1) + + x = handle.get_xdata() + y = handle.get_ydata() + if ref == 'x': + zoom_inds = (x >= x0) & (x <= x1) + elif ref == 'y': + zoom_inds = (y >= y0) & (y <= y1) + x = x[zoom_inds] + y = y[zoom_inds] + + inset_handle = inset.plot(x, y)[0] + inset_handle.set(**{prop: plt.getp(handle, prop) for prop in props}) + elements = ax.indicate_inset_zoom(inset, **kwargs) + + visibility = low_left, up_left, low_right, up_right + [l.set_visible(v) for l, v in zip(elements.connectors, visibility)] + return inset_handle, elements.rectangle, elements.connectors diff --git a/python/save_env_sd_conversion.py b/python/save_env_sd_conversion.py new file mode 100644 index 0000000..9b864af --- /dev/null +++ b/python/save_env_sd_conversion.py @@ -0,0 +1,82 @@ +import glob +import numpy as np +import matplotlib.pyplot as plt +from thunderhopper.modeltools import load_data +from thunderhopper.filters import sosfilter +from IPython import embed + +# GENERAL SETTINGS: +target = 'Omocestus_rufipes' +data_path = glob.glob(f'../data/processed/{target}*.npz')[0] +save_path = '../data/inv/noise_env/' + +# ANALYSIS SETTINGS: +scales = np.geomspace(0.1, 10000, 200) +sd_inputs = np.arange(10.9, 11.1, 0.01) +n_trials = 10 +tol_to_one = 0.1 + +# EXECUTION: + +# Load signal data: +data, config = load_data(data_path, files='filt') +signal, rate = data['filt'], config['rate'] + +# Reduce to song segment and normalize: +time = np.arange(signal.shape[0]) / rate +start, end = data['songs_0'].ravel() +segment = (time >= start) & (time <= end) +signal /= signal[segment].std() + +# Get rescaled signals (time, scale): +signal = signal[:, None] * scales[None, :] + +# Prepare storage: +current_match = 0 +storage = dict( + scales=scales, + n_trials=n_trials, + sd_factor=np.array([0.]), + trials=np.zeros((scales.size, n_trials), dtype=float), + mean=np.zeros(scales.size, dtype=float), + spread=np.zeros(scales.size, dtype=float), +) + +# Analyze piece-wise: +rng = np.random.default_rng() +for i, sigma in enumerate(sd_inputs): + print(f'Testing SD: {sigma:.3f} ...') + + # Add Gaussian noise of given SD to rescaled signals (time, scale, trial): + mix = signal[..., None] + rng.normal(0, sigma, (*signal.shape, n_trials)) + + # Get mixture envelopes (time, scale, trial): + mix = sosfilter(np.abs(mix), rate, config['env_fcut'], 'lp', + padtype='even', padlen=config['padlen'])[segment, ...] + + # Get noise remainders of mean over trials: + mix -= mix.mean(axis=-1, keepdims=True) + + # Estimate noise SD: + sd = mix.std(axis=0) + mean_sd = sd.mean(axis=-1) + n_match = (np.abs(1 - mean_sd) <= tol_to_one).sum() + if n_match > current_match: + print(f'Found better SD: {sigma:.3f} with {n_match} matches (previous: {current_match})') + storage['sd_factor'][0] = sigma + storage['trials'][:, :] = sd + storage['mean'][:] = mean_sd + storage['spread'][:] = sd.std(axis=-1) + current_match = n_match + del mix +del signal +if save_path is not None: + np.savez(save_path + 'sd_conversion.npz', **storage) + +plt.plot(scales, storage['mean'], 'k') +plt.show() +embed() + +print('Done.') +embed() + diff --git a/python/save_inv_data_full.py b/python/save_inv_data_full.py index d473d3a..6efcc42 100644 --- a/python/save_inv_data_full.py +++ b/python/save_inv_data_full.py @@ -3,6 +3,7 @@ import numpy as np import matplotlib.pyplot as plt from thunderhopper.modeltools import load_data, save_data from thunderhopper.filetools import crop_paths +from thunderhopper.filtertools import find_kern_specs from thunderhopper.model import process_signal from IPython import embed @@ -13,9 +14,20 @@ stages = ['raw', 'filt', 'env', 'log', 'inv', 'conv', 'bi', 'feat'] save_path = '../data/inv/full/' # ANALYSIS SETTINGS: -example_scales = np.array([0, 0.5, 1, 5, 10]) -scales = np.geomspace(0.01, 10, 100) +example_scales = np.array([0, 1, 10, 50]) +scales = np.geomspace(0.01, 100, 100) scales = np.unique(np.concatenate((scales, example_scales))) +kernels = np.array([ + [1, 0.002], + [-1, 0.002], + [2, 0.004], + [-2, 0.004], + [3, 0.032], + [-3, 0.032] +]) +kernels = None +types = None#np.array([-1]) +sigmas = None#np.array([0.001, 0.002, 0.004, 0.008, 0.016, 0.032]) # EXECUTION: for data_path, name in zip(data_paths, crop_paths(data_paths)): @@ -25,6 +37,13 @@ for data_path, name in zip(data_paths, crop_paths(data_paths)): data, config = load_data(data_path, files='raw') song, rate = data['raw'], config['rate'] + # Reduce to kernel subset: + kern_inds = find_kern_specs(config['k_specs'], kernels, types, sigmas) + config['kernels'] = config['kernels'][:, kern_inds] + config['k_specs'] = config['k_specs'][kern_inds, :] + config['k_props'] = [config['k_props'][i] for i in kern_inds] + config['feat_thresh'] = config['feat_thresh'][kern_inds] + # Get song segment to be analyzed: time = np.arange(song.shape[0]) / rate start, end = data['songs_0'].ravel() @@ -42,14 +61,14 @@ for data_path, name in zip(data_paths, crop_paths(data_paths)): shape_low = (song.shape[0], example_scales.size) shape_high = (song.shape[0], config['k_specs'].shape[0], example_scales.size) snippets = dict( - raw=np.zeros(shape_low, dtype=float), - filt=np.zeros(shape_low, dtype=float), - env=np.zeros(shape_low, dtype=float), - log=np.zeros(shape_low, dtype=float), - inv=np.zeros(shape_low, dtype=float), - conv=np.zeros(shape_high, dtype=float), - bi=np.zeros(shape_high, dtype=float), - feat=np.zeros(shape_high, dtype=float) + snip_raw=np.zeros(shape_low, dtype=float), + snip_filt=np.zeros(shape_low, dtype=float), + snip_env=np.zeros(shape_low, dtype=float), + snip_log=np.zeros(shape_low, dtype=float), + snip_inv=np.zeros(shape_low, dtype=float), + snip_conv=np.zeros(shape_high, dtype=float), + snip_bi=np.zeros(shape_high, dtype=float), + snip_feat=np.zeros(shape_high, dtype=float) ) # Prepare measure storage: @@ -82,13 +101,31 @@ for data_path, name in zip(data_paths, crop_paths(data_paths)): # Log snippet data: if scale in example_scales: scale_ind = np.nonzero(example_scales == scale)[0][0] - snippets[stage][:, ..., scale_ind] = signals[stage] + snippets[f'snip_{stage}'][:, ..., scale_ind] = signals[stage] # Log intensity measure per stage (excluding binary): if stage in ['raw', 'filt', 'env', 'log', 'inv', 'conv']: measures[key][i] = signals[stage][segment, ...].std(axis=0) elif stage == 'feat': measures[key][i] = signals[stage][segment, :].mean(axis=0) + + # thresh_y = np.percentile(measures['measure_feat'], 99, axis=0) + # kern_types = np.unique() + # thresh_x = np.zeros(thresh_y.shape, dtype=float) + # for i, thresh in enumerate(thresh_y): + # if thresh < 0.1: + # thresh_x[i] = scales[-1] + # continue + # mask = (measures['measure_feat'][:, i] < thresh) + # thresh_x[i] = scales[np.nonzero(mask)[0][-1]] + # inds = np.argsort(thresh_x) + # print(config['k_specs'][inds, :]) + + # fig, axes = plt.subplots(1, 2) + # axes[0].plot(snippets['snip_feat'][:, inds, -1]) + # axes[1].plot(scales, measures['measure_feat'][:, inds]) + # plt.show() + # embed() # Save analysis results: if save_path is not None: diff --git a/python/save_inv_data_log-hp.py b/python/save_inv_data_log-hp.py index cfef28a..f105215 100644 --- a/python/save_inv_data_log-hp.py +++ b/python/save_inv_data_log-hp.py @@ -3,7 +3,6 @@ import numpy as np from thunderhopper.modeltools import load_data, save_data from thunderhopper.filetools import crop_paths from thunderhopper.filters import decibel, sosfilter -from thunderhopper.model import extract_env from IPython import embed # GENERAL SETTINGS: @@ -12,21 +11,18 @@ data_paths = glob.glob(f'../data/processed/{target}*.npz') save_path = '../data/inv/log_hp/' # ANALYSIS SETTINGS: -add_noise = True -single_db_ref = True -example_scales = np.array([0, 0.1, 1, 10, 100, 200]) -scales = np.geomspace(0.1, 1000, 100) -if not add_noise: - example_scales = example_scales[example_scales > 0] +add_noise = False +example_scales = np.array([0.1, 1, 10, 30, 100, 300]) +scales = np.geomspace(0.1, 10000, 1000) scales = np.unique(np.concatenate((scales, example_scales))) # EXECUTION: for data_path, name in zip(data_paths, crop_paths(data_paths)): print(f'Processing {name}') - # Get song envelope: - data, config = load_data(data_path, files='env') - song, rate = data['env'], config['env_rate'] + # Get filtered song (prior to envelope extraction): + data, config = load_data(data_path, files='filt') + song, rate = data['filt'], config['rate'] # Get song segment to be analyzed: time = np.arange(song.shape[0]) / rate @@ -40,19 +36,20 @@ for data_path, name in zip(data_paths, crop_paths(data_paths)): mix = song[:, None] * scales[None, :] if add_noise: - # Add normalized noise envelope: + # Add normalized envelopenoise: rng = np.random.default_rng() - noise = rng.normal(size=song.shape) - noise = extract_env(noise, rate, config=config) + noise = rng.normal(scale=1, size=song.shape) noise /= noise[segment].std() mix += noise[:, None] # Process mixture: - mix_log = decibel(mix, axis=None if single_db_ref else 0) + mix = sosfilter(np.abs(mix), rate, config['env_fcut'], 'lp', + padtype='even', padlen=config['padlen']) + mix_log = decibel(mix, ref=1) mix_inv = sosfilter(mix_log, rate, config['inv_fcut'], 'hp', padtype='constant', padlen=config['padlen']) - # Get "intensity measure" per stage: + # Get intensity measure per stage: measure_env = mix[segment, :].std(axis=0) measure_log = mix_log[segment, :].std(axis=0) measure_inv = mix_inv[segment, :].std(axis=0) @@ -63,9 +60,9 @@ for data_path, name in zip(data_paths, crop_paths(data_paths)): data = dict( scales=scales, example_scales=example_scales, - env=mix[:, save_inds], - log=mix_log[:, save_inds], - inv=mix_inv[:, save_inds], + snip_env=mix[:, save_inds], + snip_log=mix_log[:, save_inds], + snip_inv=mix_inv[:, save_inds], measure_env=measure_env, measure_log=measure_log, measure_inv=measure_inv, diff --git a/python/save_noise_data.py b/python/save_noise_data.py new file mode 100644 index 0000000..0cddd78 --- /dev/null +++ b/python/save_noise_data.py @@ -0,0 +1,57 @@ +import numpy as np +from thunderhopper.model import configuration, process_signal +from thunderhopper.modeltools import load_data +from IPython import embed + +## SETTINGS: + +# General: +save_path = '../data/processed/white_noise' +stages = ['filt', 'env', 'log', 'inv', 'conv', 'bi', 'feat'] +sds = [1] +dur = 10 + +# Interactivity: +reload_saved = False + +# Processing: +rate = 44100.0 +env_rate = 44100.0 +feat_rate = 44100.0 +sigmas = [0.001, 0.002, 0.004, 0.008, 0.016, 0.032] +types = [1, -1, 2, -2, 3, -3, 4, -4, 5, -5, + 6, -6, 7, -7, 8, -8, 9, -9, 10, -10] +config = configuration(env_rate, feat_rate, types=types, sigmas=sigmas) +config.update({ + 'bp_fcut': None, + 'rate_ratio': None, + 'env_fcut': 250, + 'inv_fcut': 5, + 'feat_thresh': np.load('../data/kernel_thresholds.npy') * 0.2, + 'feat_fcut': 0.5, + 'label_channels': 0, + 'label_thresh': 0.5, + }) + +## PREPARATION: + +n_samples = int(dur * env_rate) +rng = np.random.default_rng() + +# PROCESSING: + +for sd in sds: + print('Processing: SD =', sd) + + # Generate white noise signal: + noise = rng.normal(loc=0, scale=sd, size=n_samples) + + # Fetch and store representations: + save = None if save_path is None else save_path + f'_sd-{sd}.npz' + process_signal(config, stages, signal=noise, rate=rate, save=save) + + # Cross-control: + if reload_saved: + data, params = load_data(save, stages, ['songs', 'noise']) + embed() +print('Done.') diff --git a/python/save_snippet_data.py b/python/save_snippet_data.py index 6d0e55a..e52b759 100644 --- a/python/save_snippet_data.py +++ b/python/save_snippet_data.py @@ -30,7 +30,7 @@ config.update({ 'rate_ratio': None, 'env_fcut': 250, 'inv_fcut': 5, - 'feat_thresh': np.load('../data/kernel_thresholds.npy') * 0.1, + 'feat_thresh': np.load('../data/kernel_thresholds.npy') * 0.2, 'feat_fcut': 0.5, 'label_channels': 0, 'label_thresh': 0.5,