From 7a451a82fa1adae42150895610bb974a4e06e7d4 Mon Sep 17 00:00:00 2001 From: Jan Benda Date: Sat, 17 May 2025 23:39:33 +0200 Subject: [PATCH] [noisesplit] added 1% simulation --- noisesplit.py | 76 +++++++++++++++++++++++++------------------ nonlinearbaseline.tex | 4 +-- 2 files changed, 46 insertions(+), 34 deletions(-) diff --git a/noisesplit.py b/noisesplit.py index 08472e0..518056b 100644 --- a/noisesplit.py +++ b/noisesplit.py @@ -102,8 +102,9 @@ def plot_overn(ax, s, files, nmax=1e6): ax.set_xticks_log(numticks=4) ax.set_minor_xticks_log(numticks=8) else: - ax.set_ylim(1e0, 1.3e3) + ax.set_ylim(4e0, 1.3e3) #ax.set_minor_yticks_log(numticks=5) + ax.set_minor_yticks_off() ax.set_xticks_log(numticks=5) #ax.set_minor_xticks_log(numticks=6) ax.set_xlabel('segments') @@ -218,73 +219,86 @@ def plot_noise_split(ax, contrast, noise_contrast, noise_frac, axn.text(1, y, f'Intrinsic noise (${100*noise_frac:.0f}$\\,\\%)', ha='right', transform=axn.transAxes, color=s.lsNoise['color']) if noise_frac < 1: - axn.xscalebar(1, 0, 10, 'ms', ha='right') + axn.xscalebar(1, -0.1, 10, 'ms', ha='right') return axr - + if __name__ == '__main__': #cell_name = ['2012-07-03-ak-invivo-1', 0] cell_name = ['2017-07-18-ai-invivo-1', 1] # Take this! at 3% model, 5% data nsmall = 100 nlarge = 1000000 - contrast = 0.05 + contrast = 0.01 wdt = 0.0001 wnoise = whitenoise(0, 300, wdt, 0.05, rng=np.random.default_rng(51234)) wtime = np.arange(len(wnoise))*wdt s = plot_style() - fig, axs = plt.subplots(3, 4, cmsize=(s.plot_width, 0.7*s.plot_width), + fig, axs = plt.subplots(4, 4, cmsize=(s.plot_width, 0.83*s.plot_width), width_ratios=[1, 0, 1, 1, 0.15, 1]) - fig.subplots_adjust(leftm=8, rightm=1.5, topm=4, bottomm=4, - wspace=0.25, hspace=0.8) + fig.subplots_adjust(leftm=8, rightm=1.5, topm=3.5, bottomm=4, + wspace=0.25, hspace=0.6) axs[0, 2].set_visible(False) axs[0, 3].set_visible(False) - xt = -2.2 - yt = 1.3 + xt = -2.25 + yt = 1.25 # data: - axs[0, 1].text(xt, yt, 'P-unit data', fontsize='large', - transform=axs[0, 1].transAxes, color=s.punit_color1) - data_contrast, ratebase, eodf = plot_chi2_data(axs[0, 1], s, cell_name[0], + axss = axs[0] + axss[1].text(xt, yt, 'P-unit data', fontsize='large', + transform=axss[1].transAxes, color=s.punit_color1) + data_contrast, ratebase, eodf = plot_chi2_data(axss[1], s, cell_name[0], cell_name[1]) - plot_ram(axs[0, 0], data_contrast, eodf, wtime, wnoise) - axs[0, 1].text(xt + 0.9, yt, f'$r={ratebase:.0f}$\\,Hz', - transform=axs[0, 1].transAxes, fontsize='large') + plot_ram(axss[0], data_contrast, eodf, wtime, wnoise) + axss[1].text(xt + 0.9, yt, f'$r={ratebase:.0f}$\\,Hz', + transform=axss[1].transAxes, fontsize='large') - # model: + # model 5%: + axss = axs[1] + data_files = sims_path.glob(f'chi2-noisen-{cell_name[0]}-{1000*data_contrast:03.0f}-*.npz') + files, nums = sort_files(cell_name[0], data_files, 2) + axss[1].text(xt, yt, 'P-unit model', fontsize='large', + transform=axs[1, 1].transAxes, color=s.model_color1) + plot_chi2_contrast(axss[1], axss[2], s, files, nums, nsmall, nlarge) + axr1 = plot_noise_split(axss[0], data_contrast, 0, 1, wtime, wnoise) + plot_overn(axss[3], s, files, nmax=1e6) + axss[3].legend(loc='lower center', bbox_to_anchor=(0.5, 1.2), + markerfirst=False, title='$|\\chi_2|$ percentiles') + + # model 1%: + axss = axs[2] data_files = sims_path.glob(f'chi2-noisen-{cell_name[0]}-{1000*contrast:03.0f}-*.npz') files, nums = sort_files(cell_name[0], data_files, 2) - axs[1, 1].text(xt, yt, 'P-unit model', fontsize='large', - transform=axs[1, 1].transAxes, color=s.model_color1) - plot_chi2_contrast(axs[1, 1], axs[1, 2], s, files, nums, nsmall, nlarge) - axr1 = plot_noise_split(axs[1, 0], contrast, 0, 1, wtime, wnoise) - plot_overn(axs[1, 3], s, files, nmax=1e6) - axs[1, 3].legend(loc='lower center', bbox_to_anchor=(0.5, 1.1), - markerfirst=False, title='$|\\chi_2|$ percentiles') + plot_chi2_contrast(axss[1], axss[2], s, files, nums, nsmall, nlarge) + axr2 = plot_noise_split(axss[0], contrast, 0, 1, wtime, wnoise) + plot_overn(axss[3], s, files, nmax=1e6) # model noise split: + axss = axs[3] data_files = sims_path.glob(f'chi2-split-{cell_name[0]}-*.npz') files, nums = sort_files(cell_name[0], data_files, 1) - axs[2, 1].text(xt, yt, 'P-unit model', fontsize='large', - transform=axs[2, 1].transAxes, color=s.model_color1) - axs[2, 1].text(xt + 0.9, yt, f'(noise split)', fontsize='large', - transform=axs[2, 1].transAxes) - noise_contrast, noise_frac = plot_chi2_split(axs[2, 1], axs[2, 2], s, + axss[1].text(xt, yt, 'P-unit model', fontsize='large', + transform=axss[1].transAxes, color=s.model_color1) + axss[1].text(xt + 0.9, yt, f'(noise split)', fontsize='large', + transform=axss[1].transAxes) + noise_contrast, noise_frac = plot_chi2_split(axss[1], axss[2], s, files, nums, nsmall, nlarge) - axr2 = plot_noise_split(axs[2, 0], 0, noise_contrast, noise_frac, + axr3 = plot_noise_split(axss[0], 0, noise_contrast, noise_frac, wtime, wnoise) - plot_overn(axs[2, 3], s, files, nmax=1e6) + plot_overn(axss[3], s, files, nmax=1e6) fig.common_xticks(axs[:, 1]) fig.common_xticks(axs[:, 2]) fig.common_xticks(axs[:, 3]) fig.common_yticks(axs[1, 1:3]) fig.common_yticks(axs[2, 1:3]) + fig.common_yticks(axs[3, 1:3]) fig.tag([axs[0, :2], [axr1] + axs[1, 1:].tolist(), - [axr2] + axs[2, 1:].tolist()], + [axr2] + axs[2, 1:].tolist(), + [axr3] + axs[3, 1:].tolist()], xoffs=[-4.5, 1, 1, -4.5], yoffs=2) fig.savefig() print() diff --git a/nonlinearbaseline.tex b/nonlinearbaseline.tex index d08a9f6..02aeae7 100644 --- a/nonlinearbaseline.tex +++ b/nonlinearbaseline.tex @@ -494,10 +494,8 @@ Electric fish possess an additional electrosensory system, the passive or ampull \subsection{Model-based estimation of the second-order susceptibility} In the example recordings shown above (\figsrefb{fig:punit} and \fref{fig:ampullary}), we only observe nonlinear responses on the anti-diagonal of the second-order susceptibility, where the sum of the two stimulus frequencies matches the neuron's baseline firing rate, which is in line with theoretical expectations \citep{Voronenko2017,Franzen2023}. However, a pronounced nonlinear response at frequencies \foneb{} or \ftwob{}, although predicted by theory, cannot be observed. In the following, we investigate how these discrepancies can be understood. -\begin{figure*}[t] +\begin{figure*}[p] \includegraphics[width=\columnwidth]{noisesplit} - \notejb{This model in the next figure shows a triangle for 3\% contrast ...} - \notejb{We cannot really make up this twist with the 3\% contrast not converging into a triangle.} \caption{\label{fig:noisesplit} Estimation of second-order susceptibilities in the limit of weak stimuli. \figitem{A} \suscept{} estimated from $N=11$ 0.5\,s long segments of an electrophysiological recording of another low-CV P-unit (cell 2012-07-03-ak, $\fbase=120$\,Hz, CV=0.20) driven with a weak RAM stimulus with contrast 2.5\,\%. Pink edges mark the baseline firing rate where enhanced nonlinear responses are expected. \figitem[i]{B} \textit{Standard condition} of model simulations with intrinsic noise (bottom) and a RAM stimulus (top). \figitem[ii]{B} \suscept{} estimated from simulations of the cell's LIF model counterpart (cell 2012-07-03-ak, table~\ref{modelparams}) based on the same number of FFT segments $N=11$ as in the electrophysiological recording. \figitem[iii]{B} Same as \panel[ii]{B} but using $10^6$ segments. \figitem[i-iii]{C} Same as in \panel[i-iii]{B} but in the \textit{noise split} condition: there is no external RAM signal driving the model. Instead, a large part (90\,\%) of the total intrinsic noise is treated as a signal and is presented as an equivalent amplitude modulation (\signalnoise, center), while the intrinsic noise is reduced to 10\,\% of its original strength (see methods for details). Simulating one million segments, this reveals the full expected trangular structure of the second-order susceptibility.} \end{figure*}