function data = exp_osses2022(varargin)
%EXP_OSSES2022 -
%
% Usage: data = exp_osses2022(flags)
% data = exp_osses2022(..., 'idxs', models)
%
% exp_osses2021 reproduces Figs. X and XX from Osses et al. (2022), where
% the following models are compared:
% 'dau1997' : Model #1 from Dau et al., (1997)
% 'zilany2014' : Model #2 from Zilany et al., (2014)
% 'verhulst2015' : Model #3 from Verhulst et al., (2015)
% 'verhulst2018' : Model #4 from Verhulst et al., (2018)
% 'bruce2018' : Model #5 from Bruce et al., (2018)
% 'king2019' : Model #6 from King et al., (2019)
% 'relanoiborra2019' : Model #7 from Relano-Iborra et al., (2019)
% 'osses2021' : Model #8 from Osses and Kohlrausch (2021)
%
% The following flags can be specified;
%
% 'redo' Recomputes data for specified figure
%
% 'plot' Plot the output of the experiment. This is the default.
%
% 'no_plot' Don't plot, only return data.
%
% 'models' Vector selecting the models, if not all models to process.
% For example 'models',[1 3 6] shows the data for Dau et al.,
% (1997), Verhulst et al., (2015), and King et al., (2019) only.
%
% 'fig4' Reproduce Fig. 4 of Osses et al., (2022).
%
% 'fig5' Reproduce Fig. 5 of Osses et al., (2022).
%
% To display Fig. 4 of Osses et al., (2022) use :
%
% out = exp_osses2022('fig4');
%
% To display Fig. 5 of Osses et al., (2020) use :
%
% out = exp_osses2022('fig5');
%
%
% Url: http://amtoolbox.sourceforge.net/amt-0.10.0/doc/experiments/exp_osses2022.php
% Copyright (C) 2009-2020 Piotr Majdak and the AMT team.
% This file is part of Auditory Modeling Toolbox (AMT) version 1.0.0
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.
% References: Osses2022 dau1997 zilany2014 bruce2018 verhulst2015
% verhulst2018 king2019 relanoiborra2019 osses2021
% #Author: Alejandro Osses (2020-2021): Integration in the AMT
% #Author: Piotr Majdak (2021): Adaptations for the AMT 1.0
data = [];
definput.import={'amt_cache'};
definput.flags.type={'missingflag','fig3','fig3b','fig4','fig5','fig6','fig7', ...
'fig8','fig9','fig10','fig11','fig12','fig13ab','fig13cd','fig14'};
definput.flags.plot={'plot','no_plot'};
definput.keyvals.models=[];
[flags,keyvals] = ltfatarghelper({},definput,varargin);
if flags.do_missingflag
flagnames=[sprintf('%s, ',definput.flags.type{2:end-2}),...
sprintf('%s or %s',definput.flags.type{end-1},definput.flags.type{end})];
error('%s: You must specify one of the following flags: %s.',upper(mfilename),flagnames);
end;
%%%
FontSize = 13; % FontSize for all figure axes
fs = 100e3; % 100 kHz of sampling rate, this is arbitrary
dBFS = 94; % i.e., amplitude 1 = 1 Pa = 94 dB SPL re 2x10^{-5} Pa
%%% for Figs 3, 4, 5, 6 (confirm for the first figures)
models = {'dau1997','zilany2014','verhulst2015','verhulst2018','bruce2018','king2019','relanoiborra2019','osses2021'};
Colours = {'b',il_rgb('Green'),'r',il_rgb('LightSkyBlue'),il_rgb('Maroon'),'m','k',il_rgb('mediumorchid')}; % ,'k'};
Markers = {'o','s','<','>','v','^','p','d'};
MarkersSize = [10 10 10 10 10 10 10 10];
LineStyle = {'-','-','-.','-','--','-','-','-'};
LineWidth = [2 2 2 2 2 2 2 2];
if ~isempty(keyvals.models),
warning('Not all models selected');
idxs=keyvals.models;
Markers = Markers(idxs);
MarkersSize = MarkersSize(idxs);
Colours = Colours(idxs);
LineStyle = LineStyle(idxs);
LineWidth = LineWidth(idxs);
models = models(idxs);
end
N_models = length(models);
figure_handle = []; % multiple figures will be generated
figure_name = [];
%% ------ FIG 3 Osses, Verhulst, and Majdak 2021 -------------------------
if flags.do_fig3
% Params for FFT:
K = fs/2; % for FFT
% Memory allocation
h_dB = nan(K,N_models);
hmax_dB = nan(1,N_models);
h0_dB = nan(K,N_models);
k2remove = [];
label2use = [];
for k = 1:N_models
switch models{k}
case {'dau1997','king2019'}
% No middle ear filter
me_type = [];
case {'relanoiborra2019'}
me_type = 'lopezpoveda2001';
label2use{end+1} = 'relanoiborra2019, osses2021';
case 'osses2021'
% uses the same as relanoiborra (no need to calculate it again)
me_type = [];
case 'zilany2014'
me_type = 'zilany2009';
label2use{end+1} = 'zilany2014, bruce2018';
case 'bruce2018'
me_type = [];
case 'verhulst2015'
me_type = 'verhulst2015';
label2use{end+1} = 'verhulst2015';
case 'verhulst2018'
me_type = 'verhulst2018';
label2use{end+1} = 'verhulst2018';
end
if ~isempty(me_type)
[b,a] = middleearfilter(fs,me_type);
Nr_cascaded = size(b,1);
if Nr_cascaded == 1 % no cascaded
[h,w]=freqz(b,a,K);
else
h = ones(K,1);
for j = 1:Nr_cascaded
[htmp,w]=freqz(b(j,:),a(j,:),K);
h = h.*htmp;
end
end
f = w/pi*(fs/2); % freq. of the FFT bins in Hz
h_dB(:,k) = 20*log10(abs(h));
hmax_dB(k) = max(h_dB(:,k));
h0_dB(:,k) = h_dB(:,k) - hmax_dB(k);
else
k2remove = [k2remove k];
end
end
% Preparing the plots with the four middle ear filters:
models(k2remove) = [];
Colours(k2remove) = [];
Markers(k2remove) = [];
MarkersSize(k2remove) = [];
LineStyle(k2remove) = [];
LineWidth(k2remove) = [];
h_dB(:,k2remove) = [];
hmax_dB(k2remove) = [];
h0_dB(:,k2remove) = [];
%%%
b_oear = headphonefilter(fs); % Pralong filter
htmp=freqz(b_oear,1,K);
hOuter_ear = 20*log10(abs(htmp));
%%%
pl = [];
figure;
if strcmp(models{4},'relanoiborra2019')
hCombined = h0_dB(:,4) + hOuter_ear;
pl(end+1) = semilogx(f,hCombined,'--','Color',[0.5 0.5 0.5],'LineWidth',4); hold on, grid on;
end
for k = 1:length(models)
opts_plot = {'Color',Colours{k},'LineWidth',LineWidth(k),'LineStyle',LineStyle{k}};
pl(end+1) = semilogx(f,h0_dB(:,k),opts_plot{:}); hold on, grid on;
L1 = [min(f) max(f); -3 -3];
L2 = [f'; h0_dB(:,k)'];
P = il_InterX(L1,L2);
if ~isempty(P)
f_min03_low(k) = P(1,1);
f_min03_high(k) = P(1,end);
else
f_min03_low(k) = nan;
f_min03_high(k) = nan;
end
L1 = [min(f) max(f); -15 -15];
P = il_InterX(L1,L2);
if ~isempty(P)
f_min15_low(k) = P(1,1);
f_min15_high(k) = P(1,end);
else
f_min15_low(k) = nan;
f_min15_high(k) = nan;
end
end
label2use{end+1} = '(outer+middle ear)';
xlim([80 30000]);
% legend(label2use,'Location','NorthEastOutside');
hl = legend([pl(2:end) pl(1)],label2use);
set(hl,'FontSize',8);
set(gca,'FontSize',FontSize);
f2tick = [63 125 250 500 1000 2000 4000 8000 16000];
set(gca,'XTick',f2tick);
set(gca,'YTick',-21:3:3);
ylim([-23 6])
xlabel('Frequency (Hz)');
ylabel('Amplitude (dB re. max)');
% ht = title('Middle-ear frequency response');
% set(ht,'FontSize',FontSize);
Pos = get(gcf,'Position');
Pos(3:4) = [640 360]; % fix width
set(gcf,'Position',Pos);
data.figure_flag = 'do_fig3';
data.figure_handle = gcf;
data.figure_name = 'fig03-me-resp'; % middle ear response
data.description = 'Frequency response of the middle ears used in the selected models';
data.hmax_dB = hmax_dB;
data.f_min03_low = f_min03_low;
data.f_min03_high = f_min03_high;
data.f_min15_low = f_min15_low;
data.f_min15_high = f_min15_high;
data.evaluated_models = models;
end
%% ------ FIG 4 -------------------------
if flags.do_fig4
k2remove = [];
N_models_here = N_models; % Bruce2018, is removed later...
%%% 1. Generating the input signals: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Signal parameters:
dur=100e-3; % 50 ms
lvls=0:10:100; % Level of the test signals
N_lvls = length(lvls);
f0s = [1000 500 4000];
dt = 1/fs; % \Delta t in s
t=0:dt:dur-dt;
cfs = il_m2hz(401); % default characteristic frequencies from Verhulst2012
Pos34 = [500 350];
for i = 1:length(f0s)
f0_target = f0s(i);
if f0_target == 1000
idx_lvls = find(lvls==100); % 0-dB reference
else
idx_lvls = 1:N_lvls;
end
idx = find(cfs>f0_target,1,'last');
f0 = cfs(idx);
f0_lo = audtofreq(freqtoaud(f0_target)-1); % min 1 ERB
idx_off(1) = find(cfs>f0_lo,1,'last');
f0_hi = audtofreq(freqtoaud(f0_target)+1); % plus 1 ERB
idx_off(2) = find(cfs>f0_hi,1,'last');
fprintf('actual f0=%.1f Hz using Verhulst''s mapping (bin=%.0f)\n',f0,idx);
% Basis input signal
insig = zeros(length(t),N_lvls); % Memory allocation
insig_orig = sin(2*pi*f0*t(:)); % the same sinusoid will be scaled at different levels
% Up/down cosine ramp (fixed)
dur_ramp_ms = 10;
dur_ramp = round((dur_ramp_ms*1e-3)*fs); % duration ramp in samples
rp = ones(size(insig_orig));
rp(1:dur_ramp) = rampup(dur_ramp);
rp(end-dur_ramp+1:end) = rampdown(dur_ramp);
%%%
% Calibration of the input signals:
for j = idx_lvls
insig(:,j) = scaletodbspl(insig_orig,lvls(j),dBFS); % setdbspl
insig(:,j) = rp.*insig(:,j);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
N = length(lvls(idx_lvls));
vrms = nan(N,N_models); % for the on-frequency values
vrms_off_lo = nan(N,N_models); % for the off-frequency values
vrms_off_hi = nan(N,N_models); % for the off-frequency values
k_test = 1;
insig_here = insig(:,idx_lvls);
for k = 1:N_models_here
%%% Loading flags and keyvals
[fg,kv] = il_get_flags(models{k});
fc_flags = fg.fc_flags;
afb_flags = fg.afb_flags;
afb_kv = kv.afb_keyvals;
% ihc_flags = fg.ihc_flags;
noihc_flags = fg.noihc_flags;
noan_flags = fg.noan_flags; % No auditory nerve module
nomfb_flags = fg.nomfb_flags;
fname = ['fig04_' models{k} '-f0-' num2str(f0_target) '-Hz'];
c = amt_cache('get',fname,flags.cachemode);
if ~isempty(c)
bRun = 0;
out_all = c.out_all;
out_lo_all = c.out_lo_all;
out_hi_all = c.out_hi_all;
else
bRun = 1;
out_all = [];
out_lo_all = [];
out_hi_all = [];
end
if bRun
amt_disp(['Calculating ' models{k} '...']);
switch models{k}
case 'dau1997'
for j = 1:N
fc_kv = {'flow',f0,'fhigh',f0,'basef',f0,'dboffset',dBFS};
out = dau1997(insig_here(:,j),fs,fc_kv{:},afb_flags{:},noihc_flags{:},noan_flags{:});
out_all(:,end+1) = out;
fc_kv = {'flow',f0_lo,'fhigh',f0_lo,'basef',f0_lo,'dboffset',dBFS};
out = dau1997(insig_here(:,j),fs,fc_kv{:},afb_flags{:},noihc_flags{:},noan_flags{:});
out_lo_all(:,end+1) = out;
fc_kv = {'flow',f0_hi,'fhigh',f0_hi,'basef',f0_hi,'dboffset',dBFS};
out_hi = dau1997(insig_here(:,j),fs,fc_kv{:},afb_flags{:},noihc_flags{:},noan_flags{:});
out_hi_all(:,end+1) = out;
end
case 'zilany2014'
kv={'numH',0,'numM',0,'numL',0,'fiberType',4,'nrep',1};
for j = 1:N
[~,~,~,c1,c2] = zilany2014(insig_here(:,j),fs,f0,kv{:});
idxs = 1:length(insig_here); % to remove the zero padding
out = c1(:)+c2(:);
out = out(idxs);
out_all(:,end+1) = out;
[~,~,~,c1,c2] = zilany2014(insig_here(:,j),fs,f0_lo,kv{:});
out = c1(:)+c2(:);
out = out(idxs);
out_lo_all(:,end+1) = out;
[~,~,~,c1,c2] = zilany2014(insig_here(:,j),fs,f0_hi,kv{:});
out = c1(:)+c2(:);
out = out(idxs);
out_hi_all(:,end+1) = out;
end
case 'verhulst2015'
out_model = verhulst2015(insig_here,fs,fc_flags{:},afb_flags{:},noihc_flags{:},noan_flags{:});
for j = 1:N
out = out_model(j).v(:,idx);
out_all(:,end+1) = out;
out = out_model(j).v(:,idx_off(1));
out_lo_all(:,end+1) = out;
out = out_model(j).v(:,idx_off(2));
out_hi_all(:,end+1) = out;
end
case 'verhulst2018'
out_model = verhulst2018(insig_here,fs,fc_flags{:},afb_flags{:},noihc_flags{:},noan_flags{:});
for j = 1:N
out = out_model(j).v(:,idx);
out_all(:,end+1) = out;
out = out_model(j).v(:,idx_off(1));
out_lo_all(:,end+1) = out;
out = out_model(j).v(:,idx_off(2));
out_hi_all(:,end+1) = out;
end
case 'bruce2018'
kv={'numH',0,'numM',0,'numL',0,'nrep',1};
for j = 1:N
output = bruce2018(insig_here(:,j),fs,f0,kv{:});
idxs = 1:length(insig_here); % to remove the zero padding
out = output.C1(:)+output.C2(:);
out = out(idxs);
out_all(:,end+1) = out;
output = bruce2018(insig_here(:,j),fs,f0_lo,kv{:});
out = output.C1(:)+output.C2(:);
out = out(idxs);
out_lo_all(:,end+1) = out;
output = bruce2018(insig_here(:,j),fs,f0_hi, kv{:});
out = output.C1(:)+output.C2(:);
out = out(idxs);
out_hi_all(:,end+1) = out;
end
case 'king2019'
for j = 1:N
fc_kv = {'flow',f0,'fhigh',f0,'basef',f0,'dboffset',dBFS};
out = king2019(insig_here(:,j),fs,afb_kv{:},fc_kv{:},afb_flags{:},noihc_flags{:},noan_flags{:});
out_all(:,end+1) = out;
fc_kv = {'flow',f0_lo,'fhigh',f0_lo,'basef',f0_lo,'dboffset',dBFS};
out = king2019(insig_here(:,j),fs,afb_kv{:},fc_kv{:},afb_flags{:},noihc_flags{:},noan_flags{:});
out_lo_all(:,end+1) = out;
fc_kv = {'flow',f0_hi,'fhigh',f0_hi,'basef',f0_hi,'dboffset',dBFS};
out = king2019(insig_here(:,j),fs,afb_kv{:},fc_kv{:},afb_flags{:},noihc_flags{:},noan_flags{:});
out_hi_all(:,end+1) = out;
end
case 'relanoiborra2019'
for j = 1:N
fc_kv = {'flow',f0,'fhigh',f0,'basef',f0,'erbspacebw','no_ihc','no_an'};
[~,~,out] = relanoiborra2019_featureextraction(insig_here(:,j),fs,fc_kv{:},afb_flags{:});
out_all(:,end+1) = out;
fc_kv = {'flow',f0_lo,'fhigh',f0_lo,'basef',f0_lo,'erbspacebw','no_ihc','no_an'};
[~,~,out] = relanoiborra2019_featureextraction(insig_here(:,j),fs,fc_kv{:},afb_flags{:});
out_lo_all(:,end+1) = out;
fc_kv = {'flow',f0_hi,'fhigh',f0_hi,'basef',f0_hi,'erbspacebw','no_ihc','no_an'};
[~,~,out] = relanoiborra2019_featureextraction(insig_here(:,j),fs,fc_kv{:},afb_flags{:});
out_hi_all(:,end+1) = out;
end
case 'osses2021'
for j = 1:N
fc_kv = {'flow',f0,'fhigh',f0,'basef',f0,'dboffset',dBFS};
out = osses2021(insig_here(:,j),fs,fc_kv{:},afb_flags{:},noihc_flags{:},noan_flags{:});
out_all(:,end+1) = out;
fc_kv = {'flow',f0_lo,'fhigh',f0_lo,'basef',f0_lo,'dboffset',dBFS};
out = osses2021(insig_here(:,j),fs,fc_kv{:},afb_flags{:},noihc_flags{:},noan_flags{:});
out_lo_all(:,end+1) = out;
fc_kv = {'flow',f0_hi,'fhigh',f0_hi,'basef',f0_hi,'dboffset',dBFS};
out = osses2021(insig_here(:,j),fs,fc_kv{:},afb_flags{:},noihc_flags{:},noan_flags{:});
out_hi_all(:,end+1) = out;
end
end
if ~isempty(out_all)
c = [];
c.out_all = out_all;
c.out_lo_all = out_lo_all;
c.out_hi_all = out_hi_all;
amt_cache('set',fname,c);
end
end
if ~isempty(out_all)
% Now calculation of RMS values:
for j = 1:N
vrms(j,k) = il_rmsdb(out_all(:,j));
vrms_off_lo(j,k) = il_rmsdb(out_lo_all(:,j));
vrms_off_hi(j,k) = il_rmsdb(out_hi_all(:,j));
end
end
end
if i == 1
% Preparing the plots with the four middle ear filters:
models(k2remove) = [];
Colours(k2remove) = [];
Markers(k2remove) = [];
MarkersSize(k2remove) = [];
LineStyle(k2remove) = [];
LineWidth(k2remove) = [];
N_models_here = length(models); % number of models after removing
vrms(:,k2remove) = [];
vrms_off_lo(:,k2remove) = [];
vrms_off_hi(:,k2remove) = [];
end
if f0_target == 1000
v_ref_0_dB = vrms;
% v_ref_0_dB = [ -7.3561 -44.0567 -77.9298 -101.8625 -44.0567]; % calculated at 1 kHz
data.v_ref = v_ref_0_dB;
else
if f0_target == 500
prefix4title = {'a) ','b) ','c) '};
else
prefix4title = {'d) ','e) ','f) '};
end
v_ref = v_ref_0_dB;
Format = [];
for k = 1:N_models_here
Format{k} = {'Color',Colours{k},'LineStyle',LineStyle{k}, ...
'LineWidth',LineWidth(k),'Marker',Markers{k},'MarkerFaceColor','w', ...
'MarkerSize',MarkersSize(k)};
end
%%% End formatting options
figure;
for k = 1:N_models_here
pl(k)=plot(lvls,vrms(:,k)-v_ref(k),Format{k}{:});
grid on, hold on;
end
title(sprintf('%sCF at %.0f Hz, on-frequency bin',prefix4title{1},f0));
xlabel('Input level (dB SPL)');
ylabel('Output level (dB re. max)');
ylim([-103 13])
xlim([min(lvls)-5 max(lvls)+5])
set(gca,'XTick', 0:10:100)
set(gca,'YTick',-100:10:10)
figure_handle(end+1) = gcf;
figure_name{end+1} = sprintf('fig04-IO-at-%.0f-Hz',f0);
Pos = get(gcf,'Position');
Pos(3:4) = Pos34;
set(gcf,'Position',Pos);
%%%%
figure;
for k = 1:N_models_here
plot(lvls,vrms_off_lo(:,k)-v_ref(k),Format{k}{:});
grid on, hold on
end
title(sprintf('%sCF at %.0f Hz, off frequency bin (-1 ERB)',prefix4title{2},f0_lo));
xlabel('Input level (dB SPL)');
ylabel('Output level (dB re. max)');
ylim([-103 13])
xlim([min(lvls)-5 max(lvls)+5])
set(gca,'XTick', 0:10:100)
set(gca,'YTick',-100:10:10)
figure_handle(end+1) = gcf;
figure_name{end+1} = sprintf('fig04-IO-at-%.0f-Hz-off-lo',f0);
Pos = get(gcf,'Position');
Pos(3:4) = Pos34;
set(gcf,'Position',Pos);
figure;
for k = 1:N_models_here
plot(lvls,vrms_off_hi(:,k)-v_ref(k),Format{k}{:});
grid on, hold on
end
title(sprintf('%sCF at %.0f Hz, off frequency bin (+1 ERB)',prefix4title{3},f0_hi));
xlabel('Input level (dB SPL)');
ylabel('Output level (dB re. max)');
ylim([-103 13])
xlim([min(lvls)-5 max(lvls)+5])
set(gca,'XTick', 0:10:100)
set(gca,'YTick',-100:10:10)
Pos = get(gcf,'Position');
Pos(3:4) = Pos34;
set(gcf,'Position',Pos);
if i == length(f0s)
text4leg = models;
if strcmp(models{2},'zilany2014')
text4leg{2} = [text4leg{2} ',bruce2018'];
end
hl = legend(text4leg,'Location','SouthEast');
set(hl,'FontSize',8);
end
figure_handle(end+1) = gcf;
figure_name{end+1} = sprintf('fig04-IO-at-%.0f-Hz-off-hi',f0);
data(k_test).vrms = vrms;
data(k_test).vrms_off_lo = vrms_off_lo;
data(k_test).vrms_off_hi = vrms_off_hi;
data(k_test).f0 = f0;
k_test = k_test+1;
end
end
data.figure_flag = 'do_fig4';
data.figure_handle = figure_handle;
data.figure_name = figure_name;
data.models = models;
data.v_ref_0_dB = v_ref_0_dB;
data.insig = insig;
data.insig_orig = insig_orig;
data.fs = fs;
data.ramp = rp;
data.dBFS = dBFS;
data.lvls = lvls;
end
%% ------ FIG 5 Frequency selectivity ------------------------------------
if flags.do_fig5
k2remove = [];
fsig = 4000; % Hz
basef = fsig;
% - click response, QERBs and N values
dt = 1/fs;
dur_stim_total = 100e-3; % Total duration of the stimulus
% dur_click = 80e-6; % 80 us
dur_click = 100e-6; % 25 ms, 50 ms
t_clk=0:dt:dur_stim_total-dt;
clk = zeros(1,length(t_clk));
idxi = round(10e-3*fs+1);
idxf = round(idxi+dur_click*fs);
clk(idxi:idxf)=1;
idxi = round((50e-3+10e-3)*fs+1);
idxf = round(idxi+dur_click*fs);
clk(idxi:idxf)=-1;
lvls=[30 70]; % 0:10:90;
N_lvls = length(lvls);
level_factor = 2*sqrt(2)*(2e-5.*(10.^(lvls/20)));
insigs = zeros(length(clk),N_lvls);
for i=1:N_lvls
% lvl=corr_spl(i);
insigs(:,i) = level_factor(i).*clk(:);
end
% Amplitude at 30 dB: 2e-5*10^(30/20)*sqrt(2)*2;
% Amplitude at 70 dB: 2e-5*10^(70/20)*sqrt(2)*2;
N_samples = size(insigs,1);
[cf,x] = il_m2hz(401); % Get characteristic frequencies from Verhulst models
cf_max = 10000;
cf_min = 125;
%%%
N_sigs = 31; % Approximate number of bands
bin_cf_max = find(cf>cf_max,1,'last');
bin_cf_min = find(cf>cf_min,1,'last');
df_bin = floor(abs(bin_cf_max-bin_cf_min)/N_sigs);
idx_cf = bin_cf_min:-df_bin:bin_cf_max;
fc_ref = cf(idx_cf);
N_sigs = length(fc_ref); % Exact number of bands
for k = 1:N_models
%%% Loading flags and keyvals
[fg,kv] = il_get_flags(models{k});
fc_flags = fg.fc_flags;
afb_flags = fg.afb_flags;
afb_kv = kv.afb_keyvals;
noihc_flags = fg.noihc_flags;
noan_flags = fg.noan_flags; % No auditory nerve module
nomfb_flags = fg.nomfb_flags;
for j = 1:N_lvls
fname = ['fig05_' models{k} '-QERB-' num2str(lvls(j))];
c = amt_cache('get',fname,flags.cachemode);
if ~isempty(c)
bRun = 0;
outsig = c.outsig;
fc = c.fc;
else
bRun = 1;
outsig = [];
end
if bRun
amt_disp(['Calculating ' models{k} '...']);
switch models{k}
case 'dau1997'
for ii = 1:N_sigs
fc_kv = {'flow',fc_ref(ii),'fhigh',fc_ref(ii),'basef',fc_ref(ii),'dboffset',dBFS};
[outsig(:,ii),fc(ii)] = dau1997(insigs(:,j),fs,fc_kv{:},afb_flags{:},noihc_flags{:},noan_flags{:});
end
case 'zilany2014'
outsig = [];
kv={'numH',0,'numM',0,'numL',0,'fiberType',4,'nrep',1,'reptime',1.2};
for ii = 1:N_sigs
[~,~,~,c1,c2] = zilany2014(insigs(:,j),fs,fc_ref(ii),kv{:});
outsig(:,ii) = c1(:)+c2(:);
end
case 'verhulst2015'
if j == 1
outs = verhulst2015(insigs,fs,fc_flags{:},afb_flags{:},noihc_flags{:},noan_flags{:});
CF_here = outs(1).cf;
end
outsig = [];
for ii = 1:N_sigs
outsig(:,ii) = outs(j).v(:,idx_cf(ii));
end
case 'verhulst2018'
if j == 1
outs = verhulst2018(insigs,fs,fc_flags{:},afb_flags{:},noihc_flags{:},noan_flags{:});
CF_here = outs(1).cf;
end
outsig = [];
for ii = 1:N_sigs
outsig(:,ii) = outs(j).v(:,idx_cf(ii));
end
case 'bruce2018'
kv={'numH',0,'numM',0,'numL',0,'nrep',1};
outsig = [];
for ii = 1:N_sigs
output = bruce2018(insigs(:,j)',fs,fc_ref(ii),kv{:});
outsig(:,ii) = output.C1(:)+output.C2(:);
end
case 'king2019'
for ii = 1:N_sigs
fc_kv = {'flow',fc_ref(ii),'fhigh',fc_ref(ii),'basef',fc_ref(ii),'dboffset',dBFS};
[outsig(:,ii),fc(ii)] = king2019(insigs(:,j),fs,fc_kv{:},afb_flags{:},noihc_flags{:},noan_flags{:});
end
case 'relanoiborra2019'
for ii = 1:N_sigs
fc_kv = {'flow',fc_ref(ii),'fhigh',fc_ref(ii),'basef',fc_ref(ii),'erbspacebw','no_internalnoise','no_ihc','no_an'};
[~,~,outsig(:,ii),fc(ii)] = relanoiborra2019_featureextraction(insigs(:,j), fs,fc_kv{:});
end
case 'osses2021'
for ii = 1:N_sigs
fc_kv = {'flow',fc_ref(ii),'fhigh',fc_ref(ii),'basef',fc_ref(ii),'dboffset',dBFS};
[outsig(:,ii),fc(ii)] = osses2021(insigs(:,j),fs,fc_kv{:},afb_flags{:},noihc_flags{:},noan_flags{:});
end
end
if ~isempty(outsig)
c = [];
c.outsig = outsig;
c.fc = fc;
amt_cache('set',fname,c);
end
end
if k == 1
idx_CF = find(fc_ref<=basef,1,'last');
end
K = N_samples/2;
fz = (1:K)/K*(fs/2);
if ~isempty(outsig)
switch j
case 1 % Low intensity
spec_CF_lo(:,k) = 0.5*(abs(freqz(outsig(1:K,idx_CF ),1,K))+abs(freqz(outsig(K+1:end,idx_CF ),1,K))); % only first half of the samples
spec_CF_min_1ERB_lo(:,k)= 0.5*(abs(freqz(outsig(1:K,idx_CF-1),1,K))+abs(freqz(outsig(K+1:end,idx_CF-1),1,K)));
for ii = 1:length(fc_ref)
N_here = length(outsig(:,ii));
insig_here = reshape(outsig(:,ii),N_here/2,2);
for kk = 1:2
[BW_low_each(ii,kk,k), QERB_low_each(ii,kk,k),extra] = il_Get_ERB_estimation(insig_here(:,kk), fc_ref(ii), fs);
Q03_low_each(ii,kk,k) = extra.Q03;
Q10_low_each(ii,kk,k) = extra.Q10;
end
% [BW_low(ii,k), QERB_low(ii,k)] = il_Get_ERB_estimation(outsig(:,ii), fc_ref(ii), fs);
disp('')
end
case 2 % Higher intensity
spec_CF_hi(:,k) = 0.5*(abs(freqz(outsig(1:K,idx_CF),1,K))+abs(freqz(outsig(K+1:end,idx_CF),1,K)));
spec_CF_min_1ERB_hi(:,k)= 0.5*(abs(freqz(outsig(1:K,idx_CF-1),1,K))+abs(freqz(outsig(K+1:end,idx_CF-1),1,K)));
for ii = 1:length(fc_ref)
N_here = length(outsig(:,ii));
insig_here = reshape(outsig(:,ii),N_here/2,2);
for kk = 1:2
[BW_high_each(ii,kk,k), QERB_high_each(ii,kk,k),extra] = il_Get_ERB_estimation(insig_here(:,kk), fc_ref(ii), fs);
Q03_high_each(ii,kk,k) = extra.Q03;
Q10_high_each(ii,kk,k) = extra.Q10;
end
end % end ii
end % end switch j
end % end ~isempty
end % end for j
end % end for models
%%%
% Preparing the plots
models(k2remove) = [];
Colours(k2remove) = [];
Markers(k2remove) = [];
MarkersSize(k2remove) = [];
LineStyle(k2remove) = [];
LineWidth(k2remove) = [];
N_models_here = length(models); % number of models after removing
BW_low_each(:,:,k2remove) = [];
QERB_low_each(:,:,k2remove) = [];
Q03_low_each(:,:,k2remove) = [];
Q10_low_each(:,:,k2remove) = [];
BW_high_each(:,:,k2remove) = [];
QERB_high_each(:,:,k2remove) = [];
Q03_high_each(:,:,k2remove) = [];
Q10_high_each(:,:,k2remove) = [];
spec_CF_lo(:,k2remove) = [];
spec_CF_min_1ERB_lo(:,k2remove) = [];
spec_CF_hi(:,k2remove) = [];
spec_CF_min_1ERB_hi(:,k2remove) = [];
idx = find(fc_ref<= 8000);
fc_ref = fc_ref(idx);
QERB_low_each = QERB_low_each(idx,:,:);
Q03_low_each = Q03_low_each(idx,:,:);
Q10_low_each = Q10_low_each(idx,:,:);
QERB_high_each = QERB_high_each(idx,:,:);
Q03_high_each = Q03_high_each(idx,:,:);
Q10_high_each = Q10_high_each(idx,:,:);
%%% -------------------------------------------------------------------
figure;
% Analytical expressions:
fc_ref_here = [125 fc_ref 10000];
alpha = 0.3; % Shera2002, Table I, col 'human'
beta = 12.7; % Shera2002, Table I, col 'human'
Qerb_Shera_extended = beta*((fc_ref_here/1000).^alpha);
Qerb_Shera = Qerb_Shera_extended(2:end-1);
% Q10 = Qerb*0.505+0.2085; % Ibrahim2010, Eq. 40.2
pl = [];
pl(end+1) = semilogx(fc_ref_here,Qerb_Shera_extended,'-','Color',il_rgb('LightGray'),'LineWidth',5); hold on
BW_Glasberg = 24.7*(4.37*(fc_ref_here/1000)+1);
Qerb_Glasberg_extended = fc_ref_here./BW_Glasberg;
Qerb_Glasberg = Qerb_Glasberg_extended(2:end-1);
% Q10 = Qerb*0.505+0.2085; % Ibrahim2010, Eq. 40.2
pl(end+1) = plot(fc_ref_here,Qerb_Glasberg_extended,'-','Color',il_rgb('Gray'),'LineWidth',5);
for k = 1:N_models_here % little adjustments in format for the coming figures
switch models{k}
case 'dau1997'
Marker = [Markers{k} '-'];
MSize = 7;
LW = 1;
case 'zilany2014'
Marker = [Markers{k} LineStyle{k}];
MSize = 7;
LW = LineWidth(k);
otherwise
Marker = LineStyle{k};
MSize = MarkersSize(k);
LW = LineWidth(k);
end
format_kv = {Marker,'Color',Colours{k},'MarkerSize',MSize,'LineWidth',LW};
Q_low_here(:,k) = mean(QERB_low_each(:,:,k),2); % average of the positive and negative click
pl(end+1) = semilogx(fc_ref,Q_low_here(:,k),format_kv{:},'MarkerFaceColor',Colours{k}); hold on
% plot(fc_ref,QERB_higher(:,k),'s--',format_kv{:},'MarkerFaceColor','w');
end
grid on;
XT = [20 125 250 500 1000 2000 4000 8000 16000];
set(gca,'XTick',XT);
YT = 2:2:26;
set(gca,'YTick',YT);
ylim([1 27])
leg = models;
k = 2;
if strcmp(leg{k},'zilany2014')
leg{k} = 'zilany2014,bruce2018';
end
leg{end+1} = 'Shera (2001)';
leg{end+1} = 'G & M (1990)';
legend([pl(3:end) pl(1:2)],leg,'Location','NorthWest');
xlabel('Frequency (Hz)');
ylabel('Q factor');
Pos = get(gcf,'Position');
Pos(4) = 350;
set(gcf,'Position',Pos);
figure_handle(end+1) = gcf;
figure_name{end+1} = sprintf('fig05-QERB-low-level');
% ---------------------------------------------------------------------
for k = 1:N_models_here
X_ref_empirical = mean(QERB_low_each(:,:,k),2);
Y_10 = Q10_low_each(:,1,k);
Y_03 = Q03_low_each(:,1,k);
% Fit a polynomial p of degree 1 to the (x,y) data:
p10(k,:) = polyfit(X_ref_empirical,Y_10,1);
p03(k,:) = polyfit(X_ref_empirical,Y_03,1);
switch models{k}
case {'dau1997','relanoiborra2019','king2019','osses2021'}
X_ref(:,k) = Qerb_Glasberg(:);
case {'zilany2014','bruce2018','verhulst2015','verhulst2018'}
X_ref(:,k) = Qerb_Shera(:);
end
p10_with_formula(k,:) = polyfit(X_ref(:,k),Y_10,1);
p03_with_formula(k,:) = polyfit(X_ref(:,k),Y_03,1); % figure; plot(X_ref,Y_10); hold on; plot(X_ref,Y_03,'r')
Q03_recons(:,k) = X_ref(:,k)*p03_with_formula(k,1) + p03_with_formula(k,2);
% plot(X_ref(:,k),Q03_recons(:,k),format_kv{:},'MarkerFaceColor',Colours{k}); hold on
end
for k = 1:N_models_here
f_current = 125;
f_high_lim = 8000;
count(k) = 0;
while f_current < f_high_lim
count(k) = count(k)+1;
f_low(count(k),k) = f_current;
if count(k)>10000, break; end % break the loop if got stuck
% Q_here = interp1(fc_ref,X_ref(:,k),f_low(count(k),k),'linear','extrap');
Q_here = interp1(fc_ref, Q03_recons(:,k), f_low(count(k),k),'linear','extrap');
BW_here = f_low(count(k),k)/Q_here;
f_high(count(k),k) = f_low(count(k),k) + BW_here;
f_current = f_high(count(k),k);
end
%%% Fittings that can be useful to report at some point:
% idx = [2 3 4]; p10_bio = prctile(p10(idx,:),50); p03_bio = prctile(p03(idx,:),50);
% idx = [1 5 6 7]; p10_per = prctile(p10(idx,:),50); p03_per = prctile(p03(idx,:),50);
%
% idx = [2 3 4]; p10_bio_me = mean(p10(idx,:)); p03_bio_me = mean(p03(idx,:));
% idx = [1 5 6 7]; p10_per_me = mean(p10(idx,:)); p03_per_me = mean(p03(idx,:));
% figure;
% plot(X_ref,p(2)*X_ref+p(1),'k-'); hold on;
% plot(X_ref,Y_10,'or-');
% disp('')
% % Evaluate the fitted polynomial p and plot:
% f = polyval(p,X_ref);
% figure;
% plot(X_ref,Y_10,'o',X_ref,f,'-')
% legend('data','linear fit')
%%% End fittings
fc_max = max(f_high);
fc_min = f_low(1,:);
end
% Values reported in Table II:
counts = count;
erb_step = (freqtoaud(fc_max)-freqtoaud(fc_min))./(count-1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure; % Now high levels only
% Analytical expressions:
pl = [];
pl(end+1) = semilogx(fc_ref_here,Qerb_Shera_extended ,'-','Color',il_rgb('LightGray'),'LineWidth',5); hold on
pl(end+1) = plot( fc_ref_here,Qerb_Glasberg_extended,'-','Color',il_rgb('Gray') ,'LineWidth',5);
for k = 1:N_models_here
switch models{k}
case 'dau1997'
Marker = [Markers{k} '-'];
MSize = 7;
LW = 1;
case 'zilany2014'
Marker = [Markers{k} LineStyle{k}];
MSize = 7;
LW = LineWidth(k);
otherwise
Marker = LineStyle{k};
MSize = MarkersSize(k);
LW = LineWidth(k);
end
format_kv = {Marker,'Color',Colours{k},'MarkerSize',MSize, ...
'LineWidth',LW};
Q_high_here(:,k) = mean(QERB_high_each(:,:,k),2); % average of the positive and negative click
pl(end+1) = semilogx(fc_ref,Q_high_here(:,k),format_kv{:},'MarkerFaceColor',Colours{k}); hold on
% plot(fc_ref,QERB_higher(:,k),'s--',format_kv{:},'MarkerFaceColor','w');
end
grid on;
set(gca,'XTick',XT);
YT = 2:2:26;
set(gca,'YTick',YT);
ylim([1 27])
xlabel('Frequency (Hz)');
ylabel('Q factor');
Pos = get(gcf,'Position');
Pos(4) = 350;
set(gcf,'Position',Pos);
figure_handle(end+1) = gcf;
figure_name{end+1} = sprintf('fig05-QERB-high-level');
% ---------------------------------------------------------------------
figure; % Difference Low - high
% Analytical expressions:
pl = [];
for k = 1:N_models_here
switch models{k}
case 'dau1997'
Marker = [Markers{k} '-'];
MSize = 7;
LW = 1;
case 'zilany2014'
Marker = [Markers{k} LineStyle{k}];
MSize = 7;
LW = LineWidth(k);
otherwise
Marker = LineStyle{k};
MSize = MarkersSize(k);
LW = LineWidth(k);
end
format_kv = {Marker,'Color',Colours{k},'MarkerSize',MSize,'LineWidth',LW};
pl(end+1) = semilogx(fc_ref,Q_low_here(:,k)-Q_high_here(:,k),format_kv{:},'MarkerFaceColor',Colours{k}); hold on
% plot(fc_ref,QERB_higher(:,k),'s--',format_kv{:},'MarkerFaceColor','w');
end
grid on;
Pos = get(gcf,'Position');
Pos(4) = 250;
set(gcf,'Position',Pos);
set(gca,'XTick',XT);
ylim([-4.5 12.5])
YT = -4:2:12;
set(gca,'YTick',YT);
xlabel('Frequency (Hz)');
ylabel('Q factor difference');
figure_handle(end+1) = gcf;
figure_name{end+1} = sprintf('fig05-QERB-difference-high-low');
X_ref_empirical = [];
for k = 1:N_models_here
X_ref_empirical(:,k) = Q_high_here(:,k);
Y_10 = Q10_high_each(:,1,k);
Y_03 = Q03_high_each(:,1,k);
end
Q03_recons_hi = squeeze(Q03_high_each(:,1,:));
f_low = [];
f_high = [];
count = [];
for k = 1:N_models_here
f_current = 125;
f_high_lim = 8000;
count(k) = 0;
while f_current < f_high_lim
count(k) = count(k)+1;
f_low(count(k),k) = f_current;
if count(k)>10000, break; end % break the loop if got stuck
% Q_here = interp1(fc_ref,X_ref(:,k),f_low(count(k),k),'linear','extrap');
Q_here = interp1(fc_ref, Q03_recons_hi(:,k), f_low(count(k),k),'linear','extrap');
if isnan(Q_here)
Q_here = Q03_recons_hi(1,k);
end
BW_here = f_low(count(k),k)/Q_here;
f_high(count(k),k) = f_low(count(k),k) + BW_here;
f_current = f_high(count(k),k);
disp('')
% BW =
% f_high =
end
fc_max = max(f_high);
fc_min = f_low(1,:);
end
counts(2,:) = count;
erb_step(2,:) = (freqtoaud(fc_max)-freqtoaud(fc_min))./(count-1);
data.figure_handle = figure_handle;
data.figure_name = figure_name;
data.figure_flag = 'do_fig5';
data.models = models;
data.counts = counts;
data.counts_description = 'Number of bands required to cover a frequency range from 125 to 8000 Hz';
data.erb_step = erb_step;
data.erb_step_description = 'ERB spacing that would ensure filters overlapped at their -3 dB points';
end
%% ------ FIG 6 or 7 -----------------------------------------------------
if flags.do_fig6 || flags.do_fig7
k2remove = [];
N_models_here = N_models; % Bruce2018, is removed later...
t_ms_all = [];
vihc_all = [];
ti_all = [];
%%% 1. Generating the input signals: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Signal parameters:
dur = 0.08; % 80 ms
lvl = 80; % 80 dB SPL
dur_i = 0.02; % starting time for AC assessment
dur_f = 0.07; % ending time for AC assessment
% Arbitrary zero padding before and after the signal:
dur_sil = 50e-3;
sil_bef = zeros(round(dur_sil*fs),1);
idxi = length(sil_bef)+1; % index corresponding to the first signal sample after the zero padding
% AC will be calculated between dur_i and dur_f, excluding the silence:
idxi_ac = idxi+round(dur_i*fs)-1;
idxf_ac = idxi+round(dur_f*fs)-1;
[cf,x] = il_m2hz(401); % Get characteristic frequencies from Verhulst models
cf_max = 4000;
cf_min = 125;
%%%
N_sigs = 12;
vac = nan(N_models, N_sigs);
vdc = nan(size(vac));
%%% Getting f0 ('f0_method'):
df_bin = 25;
idx_cf(N_sigs) = find(cf>cf_max,1,'last');
for i = N_sigs-1:-1:1
idx_cf(i) = idx_cf(i+1)+df_bin;
end
f0 = cf(idx_cf);
%%%
dt = 1/fs; % \Delta t in s
t=0:dt:dur-dt;
for i = 1:N_sigs
insig(:,i) = sin(2*pi*f0(i)*t); % the same sinusoid will be scaled at different levels
end
% Up/down cosine ramp (fixed)
dur_ramp_ms = 5; % in ms
dur_ramp = round((dur_ramp_ms*1e-3)*fs); % duration ramp in samples
rp = ones(size(insig(:,1)));
rp(1:dur_ramp) = rampup(dur_ramp);
rp(end-dur_ramp+1:end) = rampdown(dur_ramp);
% Adjusting the signal level before the ramp and silences are added:
insig = scaletodbspl(insig,lvl,dBFS);
% Adding the silence and ramps to the signals:
insig = [repmat(sil_bef,1,N_sigs); repmat(rp,1,N_sigs).*insig];
%%%
for k = 1:N_models_here
bInclude = 1; % models with bInclude = 0 no IHC AD/DC is assessed later...
%%% Loading flags and keyvals
[fg,kv] = il_get_flags(models{k});
fc_flags = fg.fc_flags;
afb_flags = fg.afb_flags;
afb_kv = kv.afb_keyvals;
ihc_flags = fg.ihc_flags;
noan_flags = fg.noan_flags; % No auditory nerve module
nomfb_flags = fg.nomfb_flags;
%%%
fname = ['fig06_and_07_ihc-' models{k}];
c = amt_cache('get',fname,flags.cachemode);
if ~isempty(c)
bRun = 0;
vihc = c.vihc;
fs = c.fs;
fc = c.fc;
else
bRun = 1;
vihc = [];
end
amt_disp(['Calculating ' models{k} '...']);
switch models{k}
case 'dau1997'
zoom_higher(k) = 1;
if bRun
for j = 1:N_sigs
fc_here = f0(j);
fc_kv = {'flow',fc_here,'fhigh',fc_here,'basef',fc_here,'dboffset',dBFS};
[outsig,fc] = dau1997(insig(:,j),fs,fc_kv{:},afb_flags{:},ihc_flags{:},noan_flags{:});
vihc(:,j) = outsig;
end
c = [];
c.vihc = vihc;
c.fs = fs;
c.fc = fc;
amt_cache('set',fname,c);
end
case 'zilany2014'
zoom_higher(k) = 3;
if bRun
kv={'numH',0,'numM',0,'numL',0,'fiberType',4,'nrep',1};
for j = 1:N_sigs
[~,~,vihc(:,j)] = zilany2014(insig(:,j),fs,f0(j),kv{:});
end
c = [];
c.vihc = vihc;
c.fs = fs;
c.fc = fc;
amt_cache('set',fname,c);
end
case 'verhulst2015'
zoom_higher(k) = 3;
if bRun
outsig = verhulst2015(insig,fs,fc_flags{:},afb_flags{:},ihc_flags{:},noan_flags{:});
for j = 1:N_sigs
vihc(:,j) = outsig(j).ihc(:,idx_cf(j));
end
c = [];
c.vihc = vihc;
c.fs = fs;
c.fc = fc;
amt_cache('set',fname,c);
end
case 'verhulst2018'
zoom_higher(k) = 3;
if bRun
outsig = verhulst2018(insig,fs,fc_flags{:},afb_flags{:},ihc_flags{:},noan_flags{:});
for j = 1:N_sigs
vihc(:,j) = outsig(j).ihc(:,idx_cf(j));
end
c = [];
c.vihc = vihc;
c.fs = fs;
c.fc = fc;
amt_cache('set',fname,c);
end
case 'bruce2018'
bInclude = 0;
k2remove = [k2remove k];
% Code to test bruce2018, use only with selected models
% zoom_higher(k) = 3;
% if bRun
% kv={'numH',0,'numM',0,'numL',0,'nrep',1};
% for j = 1:N_sigs
% [~,output] = bruce2018(insig(:,j),fs,f0(j),kv{:});
% vihc(:,j)=output.vihc;
% end
% c = [];
% c.vihc = vihc;
% c.fs = fs;
% c.fc = fc;
% amt_cache('set',fname,c);
% end
case 'king2019'
zoom_higher(k) = 1;
if bRun
for j = 1:N_sigs
fc_here = f0(j);
fc_kv = {'flow',fc_here,'fhigh',fc_here,'basef',fc_here,'dboffset',dBFS};
[outsig,fc] = king2019(insig(:,j),fs,fc_kv{:},afb_kv{:},afb_flags{:},ihc_flags{:},noan_flags{:});
vihc(:,j) = outsig;
end
c = [];
c.vihc = vihc;
c.fs = fs;
c.fc = fc;
amt_cache('set',fname,c);
end
case 'relanoiborra2019'
zoom_higher(k) = 3;
if bRun
for j = 1:N_sigs
fc_here = f0(j);
fc_kv = {'flow',fc_here,'fhigh',fc_here,'basef',fc_here,'erbspacebw','no_an'};
[~,~,outsig,fc] = relanoiborra2019_featureextraction(insig(:,j), fs,fc_kv{:});
vihc(:,j) = outsig;
end
c = [];
c.vihc = vihc;
c.fs = fs;
c.fc = fc;
amt_cache('set',fname,c);
end
case 'osses2021'
zoom_higher(k) = 3;
if bRun
for j = 1:N_sigs
fc_here = f0(j);
fc_kv = {'flow',fc_here,'fhigh',fc_here,'basef',fc_here,'dboffset',dBFS};
[outsig,fc] = osses2021(insig(:,j),fs,fc_kv{:},afb_flags{:},ihc_flags{:},noan_flags{:});
vihc(:,j) = outsig;
end
c = [];
c.vihc = vihc;
c.fs = fs;
c.fc = fc;
amt_cache('set',fname,c);
end
end
if bInclude
dc_reg = 1:length(sil_bef);
ac_reg = idxi_ac:idxf_ac;
[ac_target,dc_target,vr] = il_get_ac_dc_osses2022(vihc,ac_reg,dc_reg);
% vrest(k) = median(vihc(1:length(sil_bef),1)); % median of the silent initial segment
vac(k,:) = ac_target;
vdc(k,:) = dc_target; % mean(vihc(idxi_ac:idxf_ac,:))-vrest(k);
vrest(k,1) = vr(1);
% Plotting: -------------------------------------------------------
% % Normalisation to 1.3 the maximum value:
offy_step = 1.5*max(max(abs(vihc)));
t_ms = 1000*(1:size(vihc,1))/fs;
t2plot = [35 105];
idxi_plot = find(t_ms<=t2plot(1),1,'last');
idxf_plot = find(t_ms<=t2plot(2),1,'last');
idxs = idxi_plot:idxf_plot-1;
v_dec_norm = (vihc-vrest(k))/offy_step; % normalisation to maximum value
idxs_N = 9:12;
v_dec_norm(:,idxs_N) = zoom_higher(k)*v_dec_norm(:,idxs_N);
idxs2store = idxs(1:5000);
t_ms_all = [t_ms_all t_ms(idxs2store)];
ti_all(end+1) = size(vihc_all,1)+1;
vihc_all = [vihc_all; v_dec_norm(idxs2store,:)];
vmin(k,:) = min(vihc(idxs2store,:));
end
end
models(k2remove) = [];
Colours(k2remove) = [];
Markers(k2remove) = [];
MarkersSize(k2remove) = [];
LineStyle(k2remove) = [];
LineWidth(k2remove) = [];
zoom_higher(k2remove) = [];
vac(k2remove,:) = [];
vdc(k2remove,:) = [];
vmin(k2remove,:) = [];
N_models_here = length(models); % number of models after removing
%%% All formatting options in one variable. The formatting options
% for the bruce2018 are overwritten for visibility reasons,
% given that it provides the same outputs of zilany2014
Format = [];
for k = 1:N_models_here
Format{k} = {'Color',Colours{k},'LineStyle',LineStyle{k}, ...
'LineWidth',LineWidth(k),'Marker',Markers{k},'MarkerFaceColor','w', ...
'MarkerSize',MarkersSize(k)};
end
%%% End formatting options
ti_all(end+1) = length(t_ms_all);
toffset = t_ms(idxs(1));
tf = 0;
idxi = 1;
YL = [-.5 N_sigs];
plt = [];
idx_split = 5;
panel_labels = {'a) ','b) ','c) ','d) ','e) ','f) ','g) '};
for k = 1:N_models_here
if strcmp(models{k},'zilany2014')
leg{k} = [panel_labels{k} 'zilany2014,bruce2018'];
else
leg{k} = [panel_labels{k} models{k}];
end
end
for k = 1:N_models_here
if k<idx_split
figure(1);
if k == 1
figure_handle(end+1) = gcf;
figure_name{end+1} = 'fig06-ihc-waveforms';
end
else
figure(2);
if k == idx_split
figure_handle(end+1) = gcf;
figure_name{end+1} = 'fig06-ihc-waveforms-2';
end
end
idxi = ti_all(k);
idxf = ti_all(k+1)-1;
t_here = t_ms_all(idxi:idxf);
vihc_here = vihc_all(idxi:idxf,:);
for j = 1:N_sigs
offy = j-1; % (j-1) lower to higher freqs from bottom to top. Use (N_sigs-j) otherwise
if j == 1
plt(end+1) = plot(t_here-toffset+tf,vihc_here(:,j)+offy,'Color',Colours{k});
else
plot(t_here-toffset+tf,vihc_here(:,j)+offy,'Color',Colours{k});
end
hold on
if j == 1 && (k == 1 || k == idx_split)
ylim(YL);
end
plot(tf*[1 1],YL,'k-');
if (k == 1 || k == idx_split)
text(2,offy+.3,sprintf('%.0f Hz',f0(j)),'Color','k','FontSize',8);
grid on
dur_plot = 1000*length(idxs2store)/fs;
XL = [0 (idx_split-1)*dur_plot];
xlim(XL);
Pos = get(gcf,'Position');
Pos(3:4) = [650 600];
set(gcf,'Position',[0 0 650 650]);
XT = 0:10:XL(end);
XTL = [0 repmat([10:10:dur_plot],1,(idx_split-1))];
XT(dur_plot/10+1:dur_plot/10:end) = [];
XTL(dur_plot/10+1:dur_plot/10:end) = [];
set(gca,'XTick',XT);
set(gca,'XTickLabel',XTL);
YT = 0:N_sigs;
set(gca,'YTick',YT);
set(gca,'YTickLabel','');
end
if j >= 9
if k < idx_split
text((k*dur_plot-8),offy-.05,sprintf('x %.0f',zoom_higher(k)),'Color','k','FontSize',8);
else
text(((k-idx_split+1)*dur_plot-8),offy-.05,sprintf('x %.0f',zoom_higher(k)),'Color','k','FontSize',8);
end
end
end % end for j
if mod(k,4) == 0
x_coor = (4-1)*.25+.02;
else
x_coor = ((mod(k,4))-1)*.25+.02;
end
y_coor = .98;
text(x_coor,y_coor,leg{k},'Units','Normalize','FontSize',8);
if k == idx_split-1
tf = 0;
else
tf = tf+(t_here(end)+dt*1000-toffset);
end
ylabel('Amplitude (a.u.)');
xlabel('Time (ms)');
end
plot(tf*[1 1],YL,'k-'); % last time for the second figure
ra = vac ./vdc;
hl = [];
% Fig. 7 --------------------------------------------------------------
figure;
for k = 1:N_models_here
pl(k) = loglog(f0,ra(k,:),Format{k}{:}); grid on, hold on
xlabel('Frequency (Hz)');
ylabel('IHC AC/DC ratio');
end
set(gca,'XTick',[80 125 250 500 1000 2000 4000 8000]);
YT = get(gca,'YTick');
set(gca,'YTickLabel',YT)
xlim([100 6000])
ylim([0.008 180])
leg = models;
if strcmp(leg{2},'zilany2014')
leg{2} = 'zilany2014,bruce2018';
end
legend(hl,leg,'Location','SouthWest')
figure_handle(end+1) = gcf;
figure_name{end+1} = 'fig07-IHC-AC-DC';
data.figure_flag = 'do_fig6 or do_fig7';
data.figure_handle = figure_handle;
data.figure_name = figure_name;
data.insig = insig;
data.fs = fs;
data.ramp = rp;
data.models = models;
data.ACDCratio = ra;
data.AC = vac;
data.DC = vdc;
data.dBFS = dBFS;
data.lvl = lvl;
data.f0_approx = round(f0');
data.f0_exact = round(cf(idx_cf)');
data.vrest = vrest;
data.vmin = vmin;
end
%% ------ FIG. 8 ---------------------------------------------------------
if flags.do_fig8
outsig_all = [];
t_an_all = [];
psth_binwidth = 0.5e-3; % width of the PSTH bin, in seconds
nrep=100; % number of repetitions in PSTH calculations
% 1. Stimulus creation:
dur = 300e-3; % 300 ms
lvl = 70;
dBFS = 94; % AMT default
t = (1:dur*fs)/fs; t = t(:); % creates 't' as a column array
fc = 4000;
dur_ramp_ms = 2.5;
dur_ramp = round((dur_ramp_ms*1e-3)*fs); % duration ramp in samples
insig = sin(2*pi*fc.*t);
insig = scaletodbspl(insig,lvl,dBFS); % calibration before applying the ramp
rp = ones(size(insig));
rp(1:dur_ramp) = rampup(dur_ramp);
rp(end-dur_ramp+1:end) = rampdown(dur_ramp);
insig = rp.*insig;
insig = [zeros(50e-3*fs,1); insig; zeros(200e-3*fs,1)]; % 50 and 200 ms
% of silence before and after the sine tone
ti_steady = 300*1e-3; % ms
tf_steady = 340*1e-3; % ms
for k = 1:N_models
%%% Loading flags and keyvals
[fg,kv] = il_get_flags(models{k});
afb_flags = fg.afb_flags;
ihc_flags = fg.ihc_flags;
an_flags = fg.an_flags;
an_kv = kv.an_keyvals;
nomfb_flags = fg.nomfb_flags;
%%%
fname = ['fig08_' models{k} '-an-wave'];
c = amt_cache('get',fname,flags.cachemode);
if ~isempty(c)
bRun = 0;
outsig = c.outsig;
fs_an = c.fs_an;
fc = c.fc;
if isfield(c,'out_psTH')
out_psTH = c.out_psTH;
end
else
bRun = 1;
outsig = [];
end
YTL = []; % empty tick label
if bRun
amt_disp(['Calculating ' models{k} '...']);
switch models{k}
case 'dau1997'
fc_kv = {'flow',fc,'fhigh',fc,'basef',fc,'dboffset',dBFS};
outsig = dau1997(insig,fs,fc_kv{:},afb_flags{:}, ...
ihc_flags{:},an_flags{:},nomfb_flags{:});
fs_an = fs;
c = [];
c.outsig = outsig;
c.fs_an = fs_an;
c.fc = fc;
amt_cache('set',fname,c);
case 'zilany2014'
kv={'fiberType',4,'numH',12,'numM',4,'numL',4,'nrep',nrep,'psth_binwidth',psth_binwidth};
[outsig,psth] = zilany2014(insig,fs,fc,kv{:});
fs_an = fs;
out_psTH.psth = psth;
out_psTH.psth_binwidth = psth_binwidth;
c = [];
c.outsig = outsig;
c.fs_an = fs_an;
c.fc = fc;
c.out_psTH = out_psTH;
amt_cache('set',fname,c);
case 'verhulst2015'
fc_flag = fc; % one frequency will be simulated only
out = verhulst2015(insig,fs,fc_flag,an_flags{:},an_kv{:},nomfb_flags{:});
outsig = out(1).an_summed/19;
fs_an = 20000;
c = [];
c.outsig = outsig;
c.fs_an = fs_an;
c.fc = fc;
amt_cache('set',fname,c);
case 'verhulst2018'
fc_flag = fc; % one frequency will be simulated only
out = verhulst2018(insig,fs,fc_flag,an_flags{:},an_kv{:},nomfb_flags{:});
outsig = out(1).an_summed/19;
fs_an = 20000;
c = [];
c.outsig = outsig;
c.fs_an = fs_an;
c.fc = fc;
amt_cache('set',fname,c);
case 'bruce2018'
kv = {'numH',12,'numM',4,'numL',4,'psthbinwidth_mr',psth_binwidth,'nrep',nrep};
out = bruce2018(insig,fs,fc,kv{:});
outsig = out.meanrate;
out_psTH.psth = out.psth; %neurogram_ft/nrep*250; %/2/(size(out.psth_ft,3));
out_psTH.psth_binwidth = psth_binwidth; %out.t_ft(2);
fs_an = fs;
c = [];
c.outsig = outsig;
c.fs_an = fs_an;
c.fc = fc;
c.out_psTH = out_psTH;
amt_cache('set',fname,c);
case 'king2019'
fc_kv = {'flow',fc,'fhigh',fc,'basef',fc,'dboffset',dBFS,'compression_n',0.3};
outsig = king2019(insig,fs,fc_kv{:},afb_flags{:}, ...
ihc_flags{:},an_flags{:},nomfb_flags{:});
fs_an = fs;
c = [];
c.outsig = outsig;
c.fs_an = fs_an;
c.fc = fc;
amt_cache('set',fname,c);
case 'relanoiborra2019'
fc_kv = {'flow',fc,'fhigh',fc,'basef',fc,'erbspacebw'};
[~,~,outsig] = relanoiborra2019_featureextraction(insig, fs,fc_kv{:});
fs_an = fs;
c = [];
c.outsig = outsig;
c.fs_an = fs_an;
c.fc = fc;
amt_cache('set',fname,c);
case 'osses2021'
fc_kv = {'flow',fc,'fhigh',fc,'basef',fc,'dboffset',dBFS};
outsig = osses2021(insig,fs,fc_kv{:},afb_flags{:}, ...
ihc_flags{:},an_flags{:},nomfb_flags{:});
fs_an = fs;
c = [];
c.outsig = outsig;
c.fs_an = fs_an;
c.fc = fc;
amt_cache('set',fname,c);
end
end
switch models{k}
case {'zilany2014','bruce2018'}
pst_hist = out_psTH.psth;
dt = out_psTH.psth_binwidth;
t_psth = (1:length(pst_hist))*dt;
end
t_an = (1:length(outsig))/fs_an;
t_an = t_an(:); % creates 't_an' as a column array
outsig_all{k} = outsig;
t_an_all{k} = t_an;
id_steady = find(t_an>=ti_steady & t_an<=tf_steady);
onset = max(outsig);
steady = mean(outsig(id_steady));
ra(k) = onset/steady;
% fprintf('%s: Onset = %.1f (amplitude units), steady = %.1f %s, ratio = %.3f\n',models{k},onset,units_amplitude,steady,units_amplitude,ra(k));
data_sim(k).onset = onset;
data_sim(k).onset = steady;
fs_an_all(k) = fs_an;
end
if flags.do_plot
if ~exist('idxs','var'), idxs=1:8; end
for k = 1:N_models
switch idxs(k)
case {1,7,8}
figure(1);
handle_data(k) = plot(t_an_all{k}*1000,outsig_all{k},'Color',Colours{k},'LineWidth',2); hold on, grid on;
if k == 1
figure_handle(end+1) = gcf; % multiple figures will be generated
figure_name{end+1} = ['fig08-tone-4-kHz-' models{k}];
end
units_amplitude = '(MU)';
YL = [-300 1500]; % a priori knowledge
stepY = 100;
YT = YL(1)+stepY:stepY:YL(2)-stepY;
if k == 1
YTL = [];
for ii = 1:length(YT)
if mod(YT(ii),200)==0
YTL{ii} = num2str(YT(ii));
else
YTL{ii} = '';
end
end
end
case {2,5}
figure;
handle_data(k) = stairs(t_psth*1000,pst_hist,'Color',0.5*Colours{k},'LineWidth',2); hold on, grid on;
plot(t_an_all{k}*1000,outsig_all{k},'Color',Colours{k},'LineWidth',2); hold on, grid on;
% if k == 2
figure_handle(end+1) = gcf; % multiple figures will be generated
figure_name{end+1} = ['fig08-tone-4-kHz-' models{k}];
% end
units_amplitude = '(spikes/s)';
YL = [0 1000]; % a priori knowledge
stepY = 100;
YT = YL(1)+stepY:stepY:YL(2)-stepY;
case {3,4}
figure(3)
handle_data(k) = plot(t_an_all{k}*1000,outsig_all{k},'Color',Colours{k},'LineWidth',2); hold on, grid on;
if k == 3
figure_handle(end+1) = gcf; % multiple figures will be generated
figure_name{end+1} = ['fig08-tone-4-kHz-' models{k}];
end
units_amplitude = '(spikes/s)';
YL = [0 1000]; % a priori knowledge
stepY = 100;
YT = YL(1)+stepY:stepY:YL(2)-stepY;
case 6
factor = 1e3;
figure;
handle_data(k) = plot(t_an_all{k}*1000,factor*outsig_all{k},'Color',Colours{k},'LineWidth',2); hold on, grid on;
if k == 6
figure_handle(end+1) = gcf; % multiple figures will be generated
figure_name{end+1} = ['fig08-tone-4-kHz-' models{k}];
end
units_amplitude = '(arbitrary units x 10^{-3})';
YL = factor*1.8e-3*[-1 1]; % a priori knowledge
stepY = factor*.3e-3;
YT = YL(1)+stepY:stepY:YL(2)-stepY;
% for i = 1:length(YT)
% YTL{end+1} = sprintf('%.4f',YT(i));
% end
end
xlabel('Time (ms)');
ylabel(['Amplitude ' units_amplitude])
set(gca,'XTick',50:50:450);
xlim([25 475]);
ylim(YL); % ([-300 1480])
set(gca,'YTick',YT);
switch k
case {1,7,8}
set(gca,'YTickLabel',YTL);
end
offy = 5;
Xhere = 1000*[t_an(min(id_steady)) t_an(max(id_steady))];
Yhere = (YL(1)+offy)*[1 1];
plot(Xhere,Yhere,'--','LineWidth',2,'Color',[0.5 0.5 0.5]);
Yhere = (YL(2)-offy)*[1 1];
plot(Xhere,Yhere,'--','LineWidth',2,'Color',[0.5 0.5 0.5]);
Yhere = YL;
Xhere = 1000*t_an(min(id_steady))*[1 1];
plot(Xhere,Yhere,'--','LineWidth',2,'Color',[0.5 0.5 0.5]);
Xhere = 1000*t_an(max(id_steady))*[1 1];
plot(Xhere,Yhere,'--','LineWidth',2,'Color',[0.5 0.5 0.5]);
Pos = get(gcf,'Position');
Pos(3:4) = [420 250]; % [320 360];
set(gcf,'Position',Pos);
end
end
data.figure_flag = 'do_fig8';
data.ra = ra;
data.insig = insig;
data.fs = fs;
data.data_sim = data_sim;
data.models = models;
data.figure_handle = figure_handle;
data.handle_data = handle_data;
data.figure_name = figure_name;
data.outsig_all = outsig_all;
data.fs_an_all = fs_an_all;
end
%% FIG 9
if flags.do_fig9
% Code adapted from testPopRateLevel_BEZ2018_mine.m
%%% 1. Generating the input signals: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Signal parameters:
CF = 4000; %8e3; % CF in Hz;
lvls = 0:10:100;
N_lvls = length(lvls);
p0 = 2e-5; % reference pressure
% dur = 50e-3; % stimulus duration in seconds
dur = 300e-3; % stimulus duration in seconds
% dur4sim = 2*dur; % duration to simulate, double as long as the input stimulus length
dur_ramp_ms = 2.5; % rise/fall time in seconds
dur_ramp = round((dur_ramp_ms*1e-3)*fs); % duration ramp in samples
t = 0:1/fs:dur-1/fs; % time vector
insig_orig = sin(2*pi*CF*t'); % column array
rp = ones(size(insig_orig));
rp(1:dur_ramp) = rampup(dur_ramp);
rp(end-dur_ramp+1:end) = rampdown(dur_ramp);
for kk = 1:N_lvls
lvl = lvls(kk);
insig(:,kk) = scaletodbspl(insig_orig,lvl,dBFS); % calibrated, unramped stimulus
end
insig = repmat(rp,1,N_lvls).*insig;
%%% End generating the signal (the level adjustment is done later)
numH = 12; % Automate this
numM = 4;
numL = 4;
numTot = numH+numM+numL;
numCum = cumsum([numL numM numH]);
rates_avg = nan(numTot,N_lvls,N_models);
rates = nan(numTot,N_lvls,N_models);
for k = 1:N_models
psTH_H = [];
psTH_M = [];
psTH_L = [];
%%% Loading flags and keyvals
[fg,kv] = il_get_flags(models{k});
afb_flags = fg.afb_flags;
ihc_flags = fg.ihc_flags;
an_flags = fg.an_flags;
nomfb_flags = fg.nomfb_flags;
an_kv = kv.an_keyvals;
%%%
fname = ['fig09_rate-level-' models{k}];
c = amt_cache('get',fname,flags.cachemode);
if ~isempty(c)
bRun = 0;
psTH_H = c.psTH_H;
psTH_M = c.psTH_M;
psTH_L = c.psTH_L;
rates = c.rates;
fs_an = c.fs_an;
idxi = c.idxi;
idxf = c.idxf;
else
bRun = 1;
% outsig = [];
end
if bRun
amt_disp(['Calculating ' models{k} '...']);
switch models{k}
case 'dau1997'
fc_kv = {'flow',CF,'fhigh',CF,'basef',CF,'dboffset',dBFS};
for kk = 1:N_lvls
psTH_H(:,kk) = dau1997(insig(:,kk),fs,fc_kv{:}, ...
afb_flags{:},ihc_flags{:},an_flags{:},nomfb_flags{:});
end
rates = [];
psTH_M = nan(size(psTH_H));
psTH_L = nan(size(psTH_H));
fs_an = fs;
ronset = round(15e-3*fs_an)+1; % start after 15 ms (strong onset)
roffset = round(dur*fs_an); % end
idxi = ronset;
idxf = roffset;
case 'zilany2014'
for kk = 1:N_lvls
kv={'fiberType',4,'numH',0,'numM',0,'numL',numL,'nrep',10};
psTH_L(:,kk) = zilany2014(insig(:,kk),fs,CF,kv{:});
kv={'fiberType',4,'numH',0,'numM',numM,'numL',0,'nrep',10};
psTH_M(:,kk) = zilany2014(insig(:,kk),fs,CF,kv{:});
kv={'fiberType',4,'numH',numH,'numM',0,'numL',0,'nrep',10};
psTH_H(:,kk) = zilany2014(insig(:,kk),fs,CF,kv{:});
kv={'fiberType',4,'numH',numH,'numM',numM,'numL',numL,'nrep',10};
rates(:,kk,k) = zilany2014(insig(:,kk),fs,CF,kv{:});
end
fs_an = fs;
ronset = round(15e-3*fs_an)+1; % start after 15 ms (strong onset)
roffset = round(dur*fs_an); % end
idxi = ronset;
idxf = roffset;
case 'verhulst2015'
fc_flag = CF;
out = verhulst2015(insig,fs,fc_flag,an_flags{:},an_kv{:},nomfb_flags{:});
for kk = 1:N_lvls
psTH_L(:,kk) = out(kk).anfL;
psTH_M(:,kk) = out(kk).anfM;
psTH_H(:,kk) = out(kk).anfH;
end
rates = [];
fs_an = out(1).fs_an;
ronset = round(15e-3*fs_an)+1; % start after 15 ms (strong onset)
roffset = round(dur*fs_an); % end
idxi = ronset;
idxf = roffset;
case 'verhulst2018'
fc_flag = CF;
out = verhulst2018(insig,fs,fc_flag,an_flags{:},an_kv{:},nomfb_flags{:});
for kk = 1:N_lvls
psTH_L(:,kk) = out(kk).anfL;
psTH_M(:,kk) = out(kk).anfM;
psTH_H(:,kk) = out(kk).anfH;
end
rates = [];
fs_an = out(1).fs_an;
ronset = round(15e-3*fs_an)+1; % start after 15 ms (strong onset)
roffset = round(dur*fs_an); % end
idxi = ronset;
idxf = roffset;
case 'bruce2018'
kv = {'numH',numH,'numM',numM,'numL',numL,'nrep',10,'outputPerSynapse'};
rates = [];
for kk = 1:N_lvls
out = bruce2018(insig(:,kk),fs,CF,kv{:});
psTH_L(:,kk)=squeeze(mean(out.meanrate(:,1,1:numL),3))';
psTH_M(:,kk)=squeeze(mean(out.meanrate(:,1,numL+1:numL+numM),3))';
psTH_H(:,kk)=squeeze(mean(out.meanrate(:,1,numL+numM+1:end),3))';
rates(:,kk,k)= squeeze(mean(out.meanrate(idxi:idxf,1,:),1));
end
fs_an = fs;
ronset = round(15e-3*fs_an)+1; % start after 15 ms (strong onset)
roffset = round(dur*fs_an); % end
idxi = ronset;
idxf = roffset;
case {'king2019'}
fc_kv = {'flow',CF,'fhigh',CF,'basef',CF,'dboffset',dBFS};
for kk = 1:N_lvls
psTH_H(:,kk) = king2019(insig(:,kk),fs,fc_kv{:}, ...
afb_flags{:},ihc_flags{:},an_flags{:},nomfb_flags{:});
end
rates = [];
psTH_M = nan(size(psTH_H));
psTH_L = nan(size(psTH_H));
fs_an = fs;
ronset = round(15e-3*fs_an)+1; % start after 15 ms (strong onset)
roffset = round(dur*fs_an); % end
idxi = ronset;
idxf = roffset;
case {'relanoiborra2019'}
fc_kv = {'flow',CF,'fhigh',CF,'basef',CF,'erbspacebw','no_internalnoise'};
for kk = 1:N_lvls
[~,~,psTH_H(:,kk)] = relanoiborra2019_featureextraction(insig(:,kk), fs,fc_kv{:});
end
rates = [];
psTH_M = nan(size(psTH_H));
psTH_L = nan(size(psTH_H));
fs_an = fs;
ronset = round(15e-3*fs_an)+1; % start after 15 ms (strong onset)
roffset = round(dur*fs_an); % end
idxi = ronset;
idxf = roffset;
case 'osses2021'
fc_kv = {'flow',CF,'fhigh',CF,'basef',CF,'dboffset',dBFS};
for kk = 1:N_lvls
psTH_H(:,kk) = osses2021(insig(:,kk),fs,fc_kv{:}, ...
afb_flags{:},ihc_flags{:},an_flags{:},nomfb_flags{:});
end
rates = [];
psTH_M = nan(size(psTH_H));
psTH_L = nan(size(psTH_H));
fs_an = fs;
ronset = round(15e-3*fs_an)+1; % start after 15 ms (strong onset)
roffset = round(dur*fs_an); % end
idxi = ronset;
idxf = roffset;
end
c = [];
c.psTH_H = psTH_H; c.psTH_M = psTH_M; c.psTH_L = psTH_L;
c.rates = rates;
c.fs_an = fs_an;
c.idxi = idxi;
c.idxf = idxf;
amt_cache('set',fname,c);
end
for kk = 1:N_lvls
rates_avg( 1:numCum(1),kk,k)= mean(psTH_L(idxi:idxf,kk));
rates_avg(numCum(1)+1:numCum(2),kk,k)= mean(psTH_M(idxi:idxf,kk));
rates_avg(numCum(2)+1:end ,kk,k)= mean(psTH_H(idxi:idxf,kk));
end
if flags.do_plot
Pos34 = [300 300]; % width and height of the resulting plot
factor = 1;
switch models{k}
case {'dau1997','relanoiborra2019','osses2021'}
figure(1);
if k == 1
figure_handle(end+1) = gcf;
figure_name{end+1} = ['fig09-AN-firing-rates-model-' models{k}];
end
YL = 'Amplitude (MU)';
YLim = [-10 190];
YT = 0:20:180;
case {'zilany2014','bruce2018'}
figure;
YL = 'Firing rate (Spikes/s)';
figure_handle(end+1) = gcf;
figure_name{end+1} = ['fig09-AN-firing-rates-model-' models{k}];
if strcmp(models{k},'zilany2014')
YLim = [-20 380];
YT = 0:30:360;
else
YLim = [-20 320];
YT = 0:30:300;
end
case {'verhulst2015','verhulst2018'}
figure
figure_handle(end+1) = gcf;
figure_name{end+1} = ['fig09-AN-firing-rates-model-' models{k}];
YL = 'Firing rate (Spikes/s)';
YLim = [-20 320];
YT = 0:30:300;
case 'king2019'
factor = 1e4;
figure;
if factor == 1e4
YL = 'Amplitude (a.u. x 10^{-4})';
else
YL = 'Amplitude (a.u.)';
end
figure_handle(end+1) = gcf;
figure_name{end+1} = ['fig09-AN-firing-rates-model-' models{k}];
YLim = 1e-4*[-0.2 5.2]*factor;
YT = (0:.5:5)*1e-4*factor;
end
switch models{k}
case {'zilany2014','bruce2018'}
plot(lvls,factor*squeeze(rates(1: 3,:,k)),'-' ,'Color',il_rgb('Gray')); hold on, grid on
plot(lvls,factor*squeeze(rates(4: 6,:,k)),'--','Color',il_rgb('Gray'));
plot(lvls,factor*squeeze(rates(7:19,:,k)),'-' ,'Color',il_rgb('Gray'));
end
hl1 = plot(lvls,factor*squeeze(rates_avg(1:numCum(1),:,k)),'o-','Color',Colours{k},'MarkerFaceColor','w','LineWidth',3,'MarkerSize',10,'MarkerFaceColor','w'); hold on, grid on
hl2 = plot(lvls,factor*squeeze(rates_avg(numCum(1)+1:numCum(2),:,k)),'s--','Color',Colours{k},'LineWidth',3,'MarkerSize',10,'MarkerFaceColor','w');
hl3 = plot(lvls,factor*squeeze(rates_avg(numCum(2)+1:numCum(3),:,k)),'d-','Color',Colours{k},'LineWidth',3,'MarkerSize',10,'MarkerFaceColor',Colours{k});
handle_dataL(k) = hl1(1);
handle_dataM(k) = hl2(1);
handle_data(k) = hl3(1);
rates_avg_all{k} = squeeze(rates_avg(7:19,:,k));
if k == 1
rates_avg_description = 'rate levels for ''HSR''';
end
end
xlim([min(lvls)-2 max(lvls)+2])
ylim(YLim)
xlabel('Stimulus Level (dB SPL)')
ylabel(YL)
set(gca,'XTick',0:10:100);
set(gca,'YTick',YT);
Pos = get(gcf,'Position');
Pos(3:4) = Pos34;
set(gcf,'Position',Pos);
end
data.figure_flag = 'do_fig9';
data.figure_handle = figure_handle;
data.figure_name = figure_name;
data.handle_data = handle_data;
data.handle_dataL = handle_dataL; % handle for LSR data
data.handle_dataM = handle_dataM; % handle for MSR data
data.models = models;
data.lvls = lvls;
data.rate_avg_all = rates_avg_all;
data.rate_avg_description = rates_avg_description;
end
%% ------ Fig 10 ---------------------------------------------------------
if flags.do_fig10
% 1. Stimulus creation:
dur = 50e-3; % 300 ms
lvls = 0:10:100;
N_lvls = length(lvls);
psth_binwidth = 0.5e-3; % width of the PSTH bin, in seconds
nrep=100;
numH = 12;
numM = 4;
numL = 4;
t = (1:dur*fs)/fs; t = t(:); % creates 't' as a column array
fc = 4000;
dur_ramp_ms = 2.5;
dur_ramp = round((dur_ramp_ms*1e-3)*fs); % duration ramp in samples
insig_orig = sin(2*pi*fc.*t);
insig = zeros(length(t),N_lvls); % memory allocation
for j = 1:N_lvls
lvl = lvls(j);
insig(:,j) = scaletodbspl(insig_orig,lvl,dBFS); % calibration before applying the ramp
end
rp = ones(size(insig,1),1);
rp(1:dur_ramp) = rampup(dur_ramp);
rp(end-dur_ramp+1:end) = rampdown(dur_ramp);
insig = repmat(rp,1,N_lvls).*insig;
insig = [zeros(50e-3*fs,N_lvls); insig]; % 50 ms of silence before and after the sine tone
ti_steady = 300*1e-3; % ms
tf_steady = 340*1e-3; % ms
for k = 1:N_models
%%% Loading flags and keyvals
[fg,kv] = il_get_flags(models{k});
afb_flags = fg.afb_flags;
ihc_flags = fg.ihc_flags;
an_flags = fg.an_flags;
an_kv = kv.an_keyvals;
nomfb_flags = fg.nomfb_flags;
%%%
fname = ['fig10_' models{k} '-adaptation-onset-steady'];
c = amt_cache('get',fname,flags.cachemode);
if ~isempty(c)
bRun = 0;
outsig = c.outsig;
fs_an = c.fs_an;
units_amplitude = c.units_amplitude;
if isfield(c,'out_psTH')
out_psTH = c.out_psTH;
end
else
bRun = 1;
outsig = [];
amt_disp(['Calculating ' models{k} '...']);
end
factor = 1; % later used for the plots
switch models{k}
case {'dau1997','osses2021'}
if bRun
fc_kv = {'flow',fc,'fhigh',fc,'basef',fc,'dboffset',dBFS};
for j = 1:N_lvls
outsig(:,j) = dau1997(insig(:,j),fs,fc_kv{:}, ...
afb_flags{:},ihc_flags{:},an_flags{:},nomfb_flags{:});
end
fs_an = fs;
% adapt_min = -230.9; % MU, Osses2018, Appendix C, page 182
% outsig = outsig - adapt_min;
units_amplitude = '(Model Units)';
c = [];
c.fs_an = fs_an;
c.outsig = outsig;
c.units_amplitude = units_amplitude;
amt_cache('set',fname,c);
end
case 'zilany2014'
if bRun
kv={'fiberType',4,'numH',numH,'numM',numM,'numL',numL,'nrep',nrep,'psth_binwidth',psth_binwidth};
for j = 1:N_lvls
[outsig(:,j),out_psTH.psth(:,j)] = zilany2014(insig(:,j),fs,fc,kv{:});
if j == 1
out_psTH.psth_binwidth = psth_binwidth;
end
end
fs_an = fs;
units_amplitude = '(spikes/s)';
c = [];
c.fs_an = fs_an;
c.outsig = outsig;
c.units_amplitude = units_amplitude;
c.out_psTH = out_psTH;
amt_cache('set',fname,c);
end
case 'verhulst2015'
if bRun
fc_flag = fc;
out = verhulst2015(insig,fs,fc_flag,an_flags{:},an_kv{:},nomfb_flags{:});
N_tot = out(1).keyvals.numH+out(1).keyvals.numM+out(1).keyvals.numL;
for j = 1:N_lvls
outsig(:,j) = out(j).an_summed/N_tot;
end
fs_an = 20000;
units_amplitude = '(spikes/s)';
c = [];
c.fs_an = fs_an;
c.outsig = outsig;
c.units_amplitude = units_amplitude;
amt_cache('set',fname,c);
end
case 'verhulst2018'
if bRun
fc_flag = fc;
out = verhulst2018(insig,fs,fc_flag,an_flags{:},an_kv{:},nomfb_flags{:});
N_tot = out(1).keyvals.numH+out(1).keyvals.numM+out(1).keyvals.numL;
for j = 1:N_lvls
outsig(:,j) = out(j).an_summed/N_tot;
end
fs_an = 20000;
units_amplitude = '(spikes/s)';
c = [];
c.fs_an = fs_an;
c.outsig = outsig;
c.units_amplitude = units_amplitude;
amt_cache('set',fname,c);
end
case 'bruce2018'
if bRun
kv = {'numH',numH,'numM',numM,'numL',numL,'psthbinwidth_mr',psth_binwidth,'nrep',nrep};
outsig=[]; out_psTH=[];
for j = 1:N_lvls
out = bruce2018(insig(:,j),fs,fc,kv{:});
outsig(:,j) = out.meanrate;
out_psTH.psth(:,j) = out.psth;
end
out_psTH.psth_binwidth = psth_binwidth;
fs_an = fs;
units_amplitude = '(spikes/s)';
c = [];
c.fs_an = fs_an;
c.outsig = outsig;
c.units_amplitude = units_amplitude;
c.out_psTH = out_psTH;
amt_cache('set',fname,c);
end
case 'king2019'
if bRun
fc_kv = {'flow',fc,'fhigh',fc,'basef',fc,'dboffset',dBFS};
for j = 1:N_lvls
outsig(:,j) = king2019(insig(:,j),fs,fc_kv{:},'compression_n',0.3, ...
afb_flags{:},ihc_flags{:},an_flags{:},nomfb_flags{:});
end
fs_an = fs;
c = [];
c.fs_an = fs_an;
c.outsig = outsig;
c.units_amplitude = units_amplitude;
amt_cache('set',fname,c);
end
factor = 1e3;
if factor == 1e3
units_amplitude = '(a.u. x 10^{-3})';
else
units_amplitude = '(a.u.)';
end
case 'relanoiborra2019'
if bRun
fc_kv = {'flow',fc,'fhigh',fc,'basef',fc,'erbspacebw'};
for j = 1:N_lvls
[~,~,outsig(:,j)] = relanoiborra2019_featureextraction(insig(:,j), fs,fc_kv{:});
end
fs_an = fs;
units_amplitude = '(a.u.)';
c = [];
c.fs_an = fs_an;
c.outsig = outsig;
c.units_amplitude = units_amplitude;
amt_cache('set',fname,c);
end
end
t_an = (1:length(outsig))/fs_an;
t_an = t_an(:); % creates 't_an' as a column array
id_steady = find(t_an>=ti_steady & t_an<=tf_steady);
onset_here = max(outsig);
steady_here = mean(outsig(id_steady,:),1);
steady_min = min(outsig(id_steady,:));
steady_max = max(outsig(id_steady,:));
onset(k,1:N_lvls) = onset_here;
steady(k,1:N_lvls) = steady_here;
ra(k,1:N_lvls) = onset_here./steady_here;
% fprintf('%s: Onset = %.1f %s, steady = %.1f %s, ratio = %.3f\n',models{k},onset,units_amplitude,steady,units_amplitude,ra(k));
if flags.do_plot
XT = 0:10:100;
Pos34 = [300 300];
switch models{k}
case {'dau1997','relanoiborra2019','osses2021'} % dau1997
figure(1);
if k == 1
figure_handle(end+1) = gcf; % multiple figures will be generated
figure_name{end+1} = sprintf('fig10-tone-4-kHz-IO-onset-%s',models{k});
end
YL = [-50 1650];
stepY = 100;
YT = 0:stepY:1600;
if k == 1
YTL = [];
for ii = 1:length(YT)
if mod(YT(ii),200)==0
YTL{ii} = num2str(YT(ii));
else
YTL{ii} = '';
end
end
end
case {'zilany2014','bruce2018'} % zilany and bruce
figure;
figure_handle(end+1) = gcf; % multiple figures will be generated
figure_name{end+1} = sprintf('fig10-tone-4-kHz-IO-onset-%s',models{k});
YL = [-50 1650];
stepY = 100;
YT = 0:stepY:1600;
case {'verhulst2015','verhulst2018'}
figure;
figure_handle(end+1) = gcf; % multiple figures will be generated
figure_name{end+1} = sprintf('fig10-tone-4-kHz-IO-onset-%s',models{k});
YL = [-50 1650];
stepY = 100;
YT = 0:stepY:1600;
case 'king2019'
figure;
figure_handle(end+1) = gcf; % multiple figures will be generated
figure_name{end+1} = sprintf('fig10-tone-4-kHz-IO-onset-%s',models{k});
YL = [-0.2 5.2]*1e-3*factor;
YT = (0:.5:5)*1e-3*factor;
end
plot(lvls,factor*onset_here,'Color',Colours{k},'Marker',Markers{k},'LineWidth',2,'MarkerFaceColor',Colours{k});
hold on, grid on;
switch models{k}
case {'zilany2014','bruce2018'}
onset_psTH = max(out_psTH.psth);
plot(lvls,factor*onset_psTH,'--','Color',0.5*Colours{k},'Marker',Markers{k},'LineWidth',2,'MarkerFaceColor','w');
hold on, grid on;
end
xlabel('Input level (dB)');
ylabel(sprintf('Onset amplitude %s',units_amplitude));
Pos = get(gcf,'Position');
Pos(3:4) = Pos34;
set(gcf,'Position',Pos);
xlim([-3 103]);
set(gca,'XTick',XT);
ylim(YL);
set(gca,'YTick',YT);
if ~strcmp(models{k},'king2019')
% For all models except King that has another scaling
set(gca,'YTickLabel',YTL);
end
end
end
data.figure_flag = 'do_fig10';
data.ra = ra;
data.onset = onset;
data.steady = steady;
data.figure_handle = figure_handle;
data.figure_name = figure_name;
data.models = models;
end
%% ------ FIG 11 ------------------------
if flags.do_fig11
figure_handle_ax = [];
% Changes on 12/01/2021:
% - Verhulst2015 was not using the same SR, now it is...
% - The models now use fc_model=4012 Hz instead of 4000 Hz
% This is similar to Verhulst et al. 2018, Fig. 3C:
%%% 1. Generating the input signals: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Signal parameters:
fc_target = 4000; % Hz, frequency of the carrier
cf = il_m2hz(401); % Get characteristic frequencies from Verhulst models
idx_cf = find(cf>fc_target,1,'last');
fc = cf(idx_cf);
fmod = 100; % Hz, frequency of the modulator
mdepth = 1; % value between 0 and 1
dur = 500e-3; % stimulus duration in seconds
dur_ramp = 2.5e-3; % s, duration of the ramp
psth_binwidth = 0.5e-3; % width of the PSTH bin, in seconds
nrep=100;
numH = 12;
numM = 4;
numL = 4;
lvl = 60; % level, dB
N_samples = round(dur*fs);
dur_ramp_samples = round((dur_ramp)*fs);
% Creating a cosine ramp:
ramp = ones(N_samples,1);
ramp(1:dur_ramp_samples) = rampup(dur_ramp_samples);
ramp(end-dur_ramp_samples+1:end) = rampdown(dur_ramp_samples);
% AM stimulus and calibration:
t = (0:N_samples-1)/fs; t=t(:);
carrier = sin(2*pi*fc*t); % starts at phase = 0
env = (1 + mdepth * sin(2*pi*fmod*t-pi/2) ); % modulator starts at minimum (phase=-pi/2)
insig = env .* carrier; % Amplitude-modulated signal
insig = scaletodbspl(insig,lvl,dBFS);
insig = ramp.*insig;
%%%
psthbinwidth = 0.5e-3; % 0.75 ms
percent = 90; % percentage overlap
%%%
outs_anf = [];
for k = 1:N_models
%%% Loading flags and keyvals:
[fg,kv] = il_get_flags(models{k});
fc_flags = fg.fc_flags;
afb_flags = fg.afb_flags;
ihc_flags = fg.ihc_flags;
an_flags = fg.an_flags; % No auditory nerve module
nomfb_flags= fg.nomfb_flags;
an_kv = kv.an_keyvals;
fname = ['fig11_' models{k} '-an'];
c = amt_cache('get',fname,flags.cachemode);
if ~isempty(c)
bRun = 0;
an_summed = c.an_summed;
fs_an = c.fs_an;
anfH = c.anfH;
anfM = c.anfM;
anfL = c.anfL;
if isfield(c,'out_psTH')
out_psTH = c.out_psTH;
end
else
bRun = 1;
an_summed = [];
amt_disp(['Calculating ' models{k} '...']);
end
%%% Figure settings (overloaded later for dau1997):
text4ylabel='(spikes/s)';
YL = [-48 330];
factor = 1;
%%%
switch models{k}
case {'dau1997','osses2021'}
if bRun
fc_kv = {'flow',fc,'fhigh',fc,'basef',fc,'dboffset',dBFS};
out = dau1997(insig,fs,fc_kv{:},afb_flags{:}, ...
ihc_flags{:},an_flags{:},nomfb_flags{:});
fs_an = fs;
an_summed = out;
anfH = out;
anfM = 0*out;
anfL = 0*out;
c = [];
c.an_summed = an_summed;
c.fs_an = fs_an;
c.anfH = anfH;
c.anfM = anfM;
c.anfL = anfL;
amt_cache('set',fname,c);
end
text4ylabel='(MU)';
YL = [-230 330];
case {'zilany2014'}
if bRun
kv={'fiberType',4,'numH',numH,'numM',numM,'numL',numL,'nrep',nrep,'psth_binwidth',psth_binwidth};
[an_summed,out_psTH.psth] = zilany2014(insig,fs,fc,kv{:});
fs_an = fs;
anfH = an_summed;
anfM = an_summed;
anfL = an_summed;
out_psTH.psth_binwidth = psth_binwidth;
c = [];
c.an_summed = an_summed;
c.fs_an = fs_an;
c.anfH = anfH;
c.anfM = anfM;
c.anfL = anfL;
c.out_psTH = out_psTH;
amt_cache('set',fname,c);
end
case {'verhulst2015'}
if bRun
hear_profile = 'Flat00'; % NH audiogram, default
fc_kv = {'hearing_profile',hear_profile};
out = verhulst2015(insig,fs,fc_flags{:},fc_kv{:},an_kv{:},an_flags{:},nomfb_flags{:});
fs_an = out.fs_abr;
if strcmp(an_kv{1},'numH')
numH = an_kv{2};
end
if strcmp(an_kv{3},'numM')
numM = an_kv{4};
end
if strcmp(an_kv{5},'numL')
numL = an_kv{6};
end
num_tot = numH+numM+numL;
an_summed = out.an_summed(:,idx_cf)/num_tot;
anfH = out.anfH;
anfM = out.anfM;
anfL = out.anfL;
c = [];
c.an_summed = an_summed;
c.fs_an = fs_an;
c.anfH = anfH;
c.anfM = anfM;
c.anfL = anfL;
amt_cache('set',fname,c);
end
case {'verhulst2018'}
if bRun
%%% Model parameters (only one hearing profile, Flat00 and 13-3-3):
hear_profile = 'Flat00';
fc_kv = {'hearing_profile',hear_profile};
out = verhulst2018(insig,fs,fc_flags{:},fc_kv{:},an_kv{:},an_flags{:},nomfb_flags{:});
fs_an = out.fs_abr;
if strcmp(an_kv{1},'numH')
numH = an_kv{2};
end
if strcmp(an_kv{3},'numM')
numM = an_kv{4};
end
if strcmp(an_kv{5},'numL')
numL = an_kv{6};
end
num_tot = numH+numM+numL;
an_summed = out.an_summed(:,idx_cf)/num_tot;
anfH = out.anfH;
anfM = out.anfM;
anfL = out.anfL;
c = [];
c.an_summed = an_summed;
c.fs_an = fs_an;
c.anfH = anfH;
c.anfM = anfM;
c.anfL = anfL;
amt_cache('set',fname,c);
end
case {'bruce2018'}
if bRun
kv = {'numH',numH,'numM',numM,'numL',numL,'psthbinwidth_mr',psth_binwidth,'nrep',nrep};
out = bruce2018(insig,fs,fc,kv{:});
an_summed = out.meanrate;
anfH=[]; anfM = []; anfL = [];
out_psTH.psth = out.psth;
out_psTH.psth_binwidth = psth_binwidth;
fs_an = fs;
c = [];
c.fs_an = fs_an;
c.anfH = anfH;
c.anfM = anfM;
c.anfL = anfL;
c.out_psTH = out_psTH;
amt_cache('set',fname,c);
end
case 'king2019'
if bRun
fc_kv = {'flow',fc,'fhigh',fc,'basef',fc,'dboffset',dBFS};
out = king2019(insig,fs,fc_kv{:},afb_flags{:}, ...
ihc_flags{:},an_flags{:},nomfb_flags{:});
fs_an = fs;
an_summed = out;
anfH = out;
anfM = 0*out;
anfL = 0*out;
c = [];
c.fs_an = fs_an;
c.an_summed = an_summed;
c.anfH = anfH;
c.anfM = anfM;
c.anfL = anfL;
amt_cache('set',fname,c);
end
factor = 1000;
if factor == 1000
text4ylabel='(a.u. x 10^-3)';
else
text4ylabel='(a.u.)';
end
YL = 1e-3*[-1 1];
case 'relanoiborra2019'
if bRun
fc_kv = {'flow',fc,'fhigh',fc,'basef',fc,'erbspacebw'};
[~,~,out] = relanoiborra2019_featureextraction(insig, fs,fc_kv{:});
fs_an = fs;
an_summed = out;
anfH = out;
anfM = 0*out;
anfL = 0*out;
c = [];
c.fs_an = fs_an;
c.anfH = anfH;
c.anfM = anfM;
c.anfL = anfL;
c.out_psTH = out;
amt_cache('set',fname,c);
end
text4ylabel='(MU)';
YL = [-230 330];
end
t_anf = (1:length(an_summed))'/fs_an;
L_bin = round(psthbinwidth*fs_an); % samples
L_overlap = round((percent/100)*L_bin);
t_anf = buffer(t_anf, L_bin, L_overlap,'nodelay');
t_anf = t_anf(1,:);
anf = buffer(an_summed, L_bin, L_overlap,'nodelay');
anf = mean(anf); % one value per bin
if flags.do_plot
offx = 2.5;
XL = [350-offx 400+offx];
switch models{k}
case {'dau1997','relanoiborra2019','osses2021'}
if k == 1
fig_functional = figure;
figure_handle_ax(end+1) = gca;
figure_handle(end+1) = gcf;
figure_name{end+1} = ['fig11-Adaptation-' models{k}];
% title(sprintf('Model: %s -- Adaptation output\n(%.0f-%.0f-%.0f neurons; bin size=%.2f ms, %.1f percent overlap)',models{k},numH,numM,numL,psthbinwidth*1000,percent));
hold on, grid on;
else
figure(fig_functional);
end
if strcmp(models{k},'osses2021')
Style = '--';
else
Style = '-';
end
case {'zilany2014','bruce2018'}
figure;
figure_handle_ax(end+1) = gca;
figure_handle(end+1) = gcf;
figure_name{end+1} = ['fig11-Adaptation-' models{k}];
% title(sprintf('Model: %s -- Adaptation output\n(%.0f-%.0f-%.0f neurons; bin size=%.2f ms, %.1f percent overlap)',models{k},numH,numM,numL,psthbinwidth*1000,percent));
hold on, grid on;
Style = '-';
case {'verhulst2015','verhulst2018'}
if exist('fig_verhulst','var'),
figure(fig_verhulst);
else
fig_verhulst = figure;
end
figure_handle_ax(end+1) = gca;
figure_handle(end+1) = gcf;
figure_name{end+1} = ['fig11-Adaptation-' models{k}];
% title(sprintf('Model: %s -- Adaptation output\n(%.0f-%.0f-%.0f neurons; bin size=%.2f ms, %.1f percent overlap)',models{k},numH,numM,numL,psthbinwidth*1000,percent));
hold on, grid on;
Style = '-';
case 'king2019'
figure;
if k == 6
figure_handle_ax(end+1) = gca;
figure_handle(end+1) = gcf;
figure_name{end+1} = ['fig11-Adaptation-' models{k}];
% title(sprintf('Model: %s -- Adaptation output\n(%.0f-%.0f-%.0f neurons; bin size=%.2f ms, %.1f percent overlap)',models{k},numH,numM,numL,psthbinwidth*1000,percent));
hold on, grid on;
end
Style = '-';
end
plot(t_anf*1000,factor*anf,Style,'Color',Colours{k},'LineWidth',2); grid on, hold on
switch models{k}
case {'zilany2014','bruce2018'}
psth_count = out_psTH.psth;
t_psth = (1:length(psth_count))*out_psTH.psth_binwidth;
stairs(t_psth*1000,psth_count,Style,'Color',0.5*Colours{k},'LineWidth',2); grid on, hold on
outs_anf(k).psth_count = psth_count;
outs_anf(k).t_psth = t_psth;
end
xlim(XL);
ylim(factor*YL);
xlabel('Time (ms)');
ylabel(text4ylabel);
Pos = get(gcf,'Position');
Pos(3:4) = [360 400];
set(gcf,'Position',Pos);
end
outs_anf(k).t_anf = t_anf;
outs_anf(k).fs_an = fs_an;
outs_anf(k).anf = anf;
outs_anf(k).anfH = anfH;
outs_anf(k).anfM = anfM;
outs_anf(k).anfL = anfL;
end
% hl = legend(text4leg,'Location','SouthEast');
% set(hl,'FontSize',8);
data.models = models;
data.insig = insig;
data.fs = fs;
data.outs_anf = outs_anf;
data.figure_flag = 'do_fig11';
data.figure_handle = figure_handle;
data.figure_name = figure_name;
data.figure_handle_ax = figure_handle_ax;
end
%%% ------ FIG 12 Osses, Verhulst, and Majdak 2021 ---------------------
if flags.do_fig12
dur = 300e-3;
rampdur = 10e-3;
ncomponents = 10;
dB_incr = 0;
lvl = 50;
nrep=100;
numH = 12;
numM = 4;
numL = 4;
psth_binwidth=0.0005;
basef = 1000;
baseaud = freqtoaud(basef);
N_freqs = 7;
erb_step = 3;
freqs = audtofreq(baseaud-N_freqs+1:1:baseaud);
freqs4tones = freqs(1:erb_step:end);
[insig,f2test] = il_Profile_Analysis(dur, rampdur, ncomponents, dB_incr, lvl, fs,freqs4tones);
insig = insig(:);
ti = 220; % ms
tf = 270;
ti_e = ti+10; % 210;
%%%
for k = 1:length(models)
out = [];
suff_str = [];
%%% Loading flags and keyvals
[fg,kv] = il_get_flags(models{k});
afb_flags = fg.afb_flags;
ihc_flags = fg.ihc_flags;
an_flags = fg.an_flags;
nomfb_flags = fg.nomfb_flags;
an_kv = kv.an_keyvals;
%%%
fname = ['fig12_profile_' models{k}];
c = amt_cache('get',fname,flags.cachemode);
if ~isempty(c)
bRun = 0;
out = c.out;
fc = c.fc;
fs_an = c.fs_an;
else
bRun = 1;
out = [];
amt_disp(['Calculating ' models{k} '...']);
end
fc_green = il_m2hz(401);
for j = 1:N_freqs
bin_nrs(j) = find(fc_green>freqs(j),1,'last');
end
% bin_nrs = bin_nrs(1:erb_step:end);
CFs = fc_green(bin_nrs);
switch models{k}
case 'dau1997'
if bRun
for j = 1:length(CFs)
fc_kv = {'basef',CFs(j),'flow',CFs(j),'fhigh',CFs(j),'dboffset',dBFS};
out_tmp = dau1997(insig,fs,afb_flags{:},ihc_flags{:}, ...
an_flags{:},nomfb_flags{:},fc_kv{:});
out(:,j) = out_tmp;
fc(j) = freqs(j);
end
fs_an = fs;
c = [];
c.out = out;
c.fc = fc;
c.fs_an = fs_an;
amt_cache('set',fname,c);
end
fc_ref = fc;
ZL = [-240 1000];
ymax = 1600;
ymax_str = sprintf('%.0f MU',ymax/2);
extra_str = 'a) ';
case 'zilany2014'
if bRun
kv={'fiberType',4,'numH',numH,'numM',numM,'numL',numL,'nrep',nrep};
out = zilany2014(insig,fs,fc_ref,kv{:});
out = out(1:length(insig),:);
fs_an = fs;
c = [];
c.out = out;
c.fc = fc_ref;
c.fs_an = fs_an;
amt_cache('set',fname,c);
end
ymax = 1000;
ymax_str = sprintf('%.0f spikes/s',ymax/2);
extra_str = 'b) ';
case 'verhulst2015'
if bRun
out_tmp = verhulst2015(insig,fs,'abr',an_flags{:},an_kv{:},'no_cn','no_ic');
fc = fc_green(bin_nrs);
fs_an = out_tmp.fs_an;
if strcmp(kv.an_keyvals{1},'numH')
numH = kv.an_keyvals{2};
end
if strcmp(kv.an_keyvals{3},'numM')
numM = kv.an_keyvals{4};
end
if strcmp(kv.an_keyvals{5},'numL')
numL = kv.an_keyvals{6};
end
out = out_tmp.an_summed(:,bin_nrs)/(numL+numM+numH);
c = [];
c.out = out;
c.fc = fc;
c.fs_an = fs_an;
amt_cache('set',fname,c);
end
extra_str = 'c) ';
ymax = 1000;
% ymax_str = sprintf('%.0f\n spikes/s',ymax/2);
ymax_str = sprintf('%.0f spikes/s',ymax/2);
case 'verhulst2018'
if bRun
out_tmp = verhulst2018(insig,fs,'abr',an_flags{:},an_kv{:},'no_cn','no_ic');
fc = fc_green(bin_nrs);
fs_an = out_tmp.fs_an;
if strcmp(kv.an_keyvals{1},'numH')
numH = kv.an_keyvals{2};
end
if strcmp(kv.an_keyvals{3},'numM')
numM = kv.an_keyvals{4};
end
if strcmp(kv.an_keyvals{5},'numL')
numL = kv.an_keyvals{6};
end
out = out_tmp.an_summed(:,bin_nrs)/(numL+numM+numH);
c = [];
c.out = out;
c.fc = fc;
c.fs_an = fs_an;
amt_cache('set',fname,c);
end
extra_str = 'd) ';
ymax = 1000;
ymax_str = sprintf('%.0f spikes/s',ymax/2);
case 'bruce2018'
bUse_PSTH = 1;
if bRun
fc = fc_ref;
kv = {'numH',numH,'numM',numM,'numL',numL,'psthbinwidth_mr',psth_binwidth,'nrep',nrep};
tmp = bruce2018(insig,fs,fc_ref,kv{:});
out=tmp.psth;
fs_an = 1/psth_binwidth;
Nf = round(dur*fs_an);
out = out(1:Nf,:);
c = [];
c.out = out;
c.fc = fc;
c.fs_an = fs_an;
amt_cache('set',fname,c);
end
if bUse_PSTH == 0
% ZL = [0 1000];
ymax = 300;
else
ymax = 1000;
end
ymax_str = sprintf('%.0f spikes/s',ymax/2);
extra_str = 'e) ';
case 'king2019'
compression_n = 0.3; ymax = 2.5e-3; % all channels compressed
% compression_n = 1; ymax = .125;
if bRun
fc = [];
for j = 1:length(fc_ref)
fc_kv = {'basef',fc_ref(j),'flow',fc_ref(j),'fhigh',fc_ref(j),'dboffset',dBFS};
[out_tmp,fc(j)] = king2019(insig,fs,afb_flags{:},ihc_flags{:}, ...
an_flags{:},nomfb_flags{:},fc_kv{:},'compression_n',compression_n);
out(:,j) = out_tmp;
end
fs_an = fs;
c = [];
c.out = out;
c.fc = fc;
c.fs_an = fs_an;
amt_cache('set',fname,c);
end
extra_str = 'f) ';
% ymax_str = sprintf('%.4f\n a.u',ymax/2);
ymax_str = sprintf('%.4f a.u',ymax/2);
case 'relanoiborra2019'
if bRun
fc = [];
for j = 1:length(fc_ref)
fc_kv = {'basef',fc_ref(j),'flow',fc_ref(j),'fhigh',fc_ref(j),'erbspacebw'};
[~,~,out_tmp,fc(j)] = relanoiborra2019_featureextraction(insig, fs,fc_kv{:});
out(:,j) = out_tmp;
end
% out = out(:,1:2*erb_step:end);
% fc = fc(1:2*erb_step:end);
fs_an = fs;
c = [];
c.out = out;
c.fc = fc;
c.fs_an = fs_an;
amt_cache('set',fname,c);
end
ZL = [-240 1000];
ymax = 1600;
ymax_str = sprintf('%.0f MU',ymax/2);
extra_str = 'g) ';
case 'osses2021'
if bRun
for j = 1:length(fc_ref)
fc_kv = {'basef',fc_ref(j),'flow',fc_ref(j),'fhigh',fc_ref(j),'dboffset',dBFS};
out_tmp = osses2021(insig,fs,afb_flags{:},ihc_flags{:}, ...
an_flags{:},nomfb_flags{:},fc_kv{:});
out(:,j) = out_tmp;
fc(j) = fc_ref(j);
end
fs_an = fs;
c = [];
c.out = out;
c.fc = fc;
c.fs_an = fs_an;
amt_cache('set',fname,c);
end
extra_str = 'h) ';
ZL = [-240 1000];
ymax = 1600;
ymax_str = sprintf('%.0f MU',ymax/2);
end
idxi_=round(ti*1e-3*fs_an);
idxf_=round(tf*1e-3*fs_an);
offy = [];
t_ms = 1000*(1:size(insig,1))/fs;
tan_ms = 1000*(1:size(out,1))/fs_an;
bw_erb = audfiltbw(fc);
figure;
for i = 1:length(fc)
% [env_here,idx_here] = il_Get_envelope(out(:,i),fs_an,fc(i)-bw_erb(i)/2); % envelope extraction assuming 'positive neurone firing'
me = mean(out(idxi_:idxf_,i)); % looks for peaks above the avg in the steady section
[env_here,idx_here] = il_Get_envelope2(out(:,i),me);
offy(i) = (i-1);
tan_ms_here = tan_ms(idx_here);
idxs = find(tan_ms >= ti-10 & tan_ms <= tf-7.5); % 10 ms before ti
plot(tan_ms(idxs),out(idxs,i)/ymax + offy(i),'Color',Colours{k}); hold on, grid on
idxs = find(tan_ms_here >= ti-10 & tan_ms_here <= tf-7.5);
plot(tan_ms_here(idxs),env_here(idxs)/ymax + offy(i),'Color',[0.6 0.6 0.6],'LineWidth',2);
env_mean(k,i) = mean(env_here(idxs));
env_std(k,i) = std(env_here(idxs));
% text(min(t_ms(idxs_pre))+2,offy+.6,sprintf('%.0f Hz',fc(i)),'Color','k');
env_scale(k) = ymax;
end
%%% YAxis: scale
tf_here=tf-7.5-.5;
plot(tf_here*[1 1],[0 0.5],'k-','LineWidth',2);
plot([tf_here-2 tf_here],0.5*[1 1],'k-','LineWidth',2);
plot([tf_here-2 tf_here], [0 0],'k-','LineWidth',2);
text(tf_here-6,-0.35,ymax_str,'FontWeight','Bold');
%%% XAxis: scale
if k == 7 || k == 8
plot([ti_e+10 ti_e+20],-0.45*[1 1],'k-','LineWidth',2);
plot([ti_e+10 ti_e+10],[-0.45 -0.35],'k-','LineWidth',2);
plot([ti_e+20 ti_e+20],[-0.45 -0.35],'k-','LineWidth',2);
text(ti_e+10,-0.85,'10 ms','FontWeight','Bold');
end
%%%
ylabel('Simulated CF_n (Hz)')
xlim([ti tf]);
ylim([-.5 7])
YL = get(gca,'YLim');
factor_std = 40;
env_std_here = env_std(k,:)*(factor_std/env_scale(k));
plot(tf+2.5-10+env_std_here, env_mean(k,:)/ymax + offy,'o--','Color',il_rgb('Maroon'),'LineWidth',2);
plot((tf+2.5-10)*[1 1],YL,'k-');
if k == 1
x_fc = (1:length(fc));
YTL = [];
for j = 1:length(CFs)
YTL{j} = [num2str(round(CFs(j))) ' Hz'];
end
end
set(gca,'YTick',x_fc-1);
set(gca,'YTickLabel',YTL);
set(gca,'XTick',ti+10:10:tf-10);
set(gca,'XTickLabel',[])
title([extra_str models{k}])
Pos = get(gcf,'Position');
Pos(3:4) = [380 280]; % [500 300];
set(gcf,'Position',Pos);
figure_handle(end+1) = gcf;
figure_name{end+1} = ['fig12-profile-' models{k} suff_str];
disp('')
end
data.figure_flag = 'do_fig12';
data.env_mean = env_mean;
data.env_std = env_std;
data.env_scale = env_scale;
data.env_scale_std = env_scale/factor_std;
% data.env_std(8,:) ./ (env_scale(8)/factor_std)
data.insig = insig;
data.fs = fs;
data.models = models;
data.figure_handle = figure_handle;
data.figure_name = figure_name;
end
%% ------ FIG 13 ------------------------
if flags.do_fig13ab || flags.do_fig13cd
% Adapted from g20190618_investigating_IC_CN.m
%%% Stimulus generation:
if flags.do_fig13ab, L=30; else L=70; end
dBFS = 94;
fs = 100e3;
dur= 300e-3; % ms
t = 0:1/fs:dur-1/fs;
t = t(:); % column vector
fc = 1000; % 4000 % Hz
dur_samples = length(t);
numH = 12;
numM = 4;
numL = 4;
ic_delay_inh=0.0011; % 1.1 ms as in the manuscript
fmod_step = 5;
fmods = 10:fmod_step:130; % 250;
N_signals = length(fmods);
insig = zeros(dur_samples,N_signals); % Memory allocation
% Up/down cosine ramp (fixed)
dur_ramp_ms = 5;
dur_ramp = round((dur_ramp_ms*1e-3)*fs); % duration ramp in samples
rp = ones(dur_samples,1);
rp(1:dur_ramp) = rampup(dur_ramp);
rp(end-dur_ramp+1:end) = rampdown(dur_ramp);
%Stimulus
for i = 1:length(fmods)
fmod = fmods(i);
mod_index=1;
carrier=sin(2*pi*fc.*t);
modulator=mod_index*cos(2*pi*fmod.*t+pi);
insig_tmp=(1+modulator).*carrier;
insig_tmp = scaletodbspl(insig_tmp,L,dBFS);
insig(:,i) = rp.*insig_tmp;
end
ti = 190e-3;
tf = 290e-3;
for k = 1:N_models
%%% Loading flags and keyvals
[fg,kv] = il_get_flags(models{k});
afb_flags = fg.afb_flags;
ihc_flags = fg.ihc_flags;
an_flags = fg.an_flags;
an_keyvals = kv.an_keyvals;
mfb_flags = fg.mfb_flags;
mfb_keyvals = kv.mfb_keyvals;
%%%
switch L
case 70
suff_lvl='';
otherwise
suff_lvl = ['-' num2str(L) '-dB'];
end
fname = ['fig13_MTF-' models{k} suff_lvl];
c = amt_cache('get',fname,flags.cachemode);
if ~isempty(c)
bRun = 0;
outsig = c.outsig;
subfs = c.subfs;
mfc = c.mfc;
else
bRun = 1;
outsig = [];
end
mfc_target = 100;
switch models{k}
case 'dau1997'
if bRun
afb_kv = {'basef',fc,'flow',fc,'fhigh',fc,'dboffset',dBFS};
for j = 1:N_signals
[out_tmp,fc,mfc_here] = dau1997(insig(:,j),fs,afb_kv{:},afb_flags{:},ihc_flags{:},an_flags{:},mfb_flags{:});
mfc_idx = find(mfc_here<mfc_target,1,'last');
outsig(:,j) = out_tmp{1}(:,mfc_idx);
subfs = fs;
if j == 1
mfc = mfc_here(mfc_idx);
end
end
c = [];
c.outsig = outsig;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
case 'zilany2014'
if bRun
kv={'fiberType',4,'numH',numH,'numM',numM,'numL',numL,'nrep',10};
for j = 1:length(fmods)
mean_rate = zilany2014(insig(:,j),fs,fc,kv{:});
[ic_out,~,~,par] = carney2015(mean_rate,90,fs,'ic_delay_inh',ic_delay_inh);
N_samples = length(insig);
outsig(:,j) = ic_out(1:N_samples);
if j == 1
subfs = fs;
mfc = 90;
amt_disp(sprintf('Zilany2014: CN: tau_exc=%f, tan_inh=%f, D=%f, S=%f',par.tau_ex_cn,par.tau_inh_cn,par.cn_delay,par.Sinh_cn));
amt_disp(sprintf('Zilany2014: IC: tau_exc=%f, tan_inh=%f, D=%f, S=%f',par.tau_ex_ic,par.tau_inh_ic,par.ic_delay_inh,par.Sinh_ic));
end
end
c = [];
c.outsig = outsig;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
case 'verhulst2015'
if bRun
fc_green = il_m2hz(401);
idx = find(fc_green>fc,1,'last');
out = verhulst2015(insig,fs,'abr',afb_flags{:},ihc_flags{:},an_flags{:}, ...
kv.an_keyvals{:},mfb_flags{:},'no_ihc'); % no_ihc just reduce the data load here
subfs = out(1).fs_abr;
%%%
if strcmp(kv.an_keyvals{1},'numH')
numH = kv.an_keyvals{2};
end
if strcmp(kv.an_keyvals{3},'numM')
numM = kv.an_keyvals{4};
end
if strcmp(kv.an_keyvals{5},'numL')
numL = kv.an_keyvals{6};
end
numTot = numH + numM + numL;
%%%
for j = 1:length(fmods)
outsig(:,j) = out(j).ic(:,idx)/numTot;
end
mfc = [];
c = [];
c.outsig = outsig;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
case 'verhulst2018'
if bRun
fc_green = il_m2hz(401);
idx = find(fc_green>fc,1,'last');
out = verhulst2018(insig,fs,'abr',afb_flags{:},ihc_flags{:},an_flags{:}, ...
kv.an_keyvals{:},mfb_flags{:},'no_ihc','no_anfH','no_anfM','no_anfL');
subfs = out(1).fs_abr;
%%%
if strcmp(kv.an_keyvals{1},'numH')
numH = kv.an_keyvals{2};
end
if strcmp(kv.an_keyvals{3},'numM')
numM = kv.an_keyvals{4};
end
if strcmp(kv.an_keyvals{5},'numL')
numL = kv.an_keyvals{6};
end
numTot = numH + numM + numL;
%%%
for j = 1:length(fmods)
outsig(:,j) = out(j).ic(:,idx)/numTot;
end
mfc = [];
c = [];
c.outsig = outsig;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
case 'bruce2018'
if bRun
psth_binwidth=0.0005;
kv = {'numH',numH,'numM',numM,'numL',numL,'nrep',10,'psthbinwidth_mr',psth_binwidth};
N_samples = size(insig,1);
subfs = fs;
mfc = 90;
for j = 1:length(fmods)
tmp = bruce2018(insig(:,j),fs,fc,kv{:});
% This is how Carney calls her model: PSTH_FT/Number_of_fibers*Model_Sampling_rate
ic_out = carney2015(tmp.psth_ft/(numH+numM+numL)*100000,mfc,fs,'ic_delay_inh',ic_delay_inh);
outsig(:,j) = ic_out(1:N_samples);
end
c = [];
c.outsig = outsig;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
case 'relanoiborra2019'
if bRun
afb_kv = {'basef',fc,'flow',fc,'fhigh',fc,'erbspacebw'};
for j = 1:N_signals
%[out_tmp,mfc_here,~,fc(j)] = relanoiborra2019_featureextraction(insig(:,j), fs, afb_kv{:});
[out_tmp,mfc_here] = relanoiborra2019_featureextraction(insig(:,j), fs, afb_kv{:});
mfc_idx = find(mfc_here<mfc_target,1,'last');
outsig(:,j) = squeeze(out_tmp(:,1,mfc_idx));
subfs = fs;
if j == 1
mfc = mfc_here(mfc_idx);
end
end
c = [];
c.outsig = outsig;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
case 'king2019'
if bRun
for j = 1:N_signals
afb_kv = {'basef',fc,'flow',fc,'fhigh',fc,'compression_n',.3,'dboffset',dBFS,'subfs',20000};
[out_tmp,fc,mfc_here,extras] = king2019(insig(:,j),fs,afb_kv{:});
mfc_idx = find(mfc_here<mfc_target,1,'last');
out_tmp = squeeze(out_tmp);
mfc = mfc_here(mfc_idx);
outsig(:,j) = out_tmp(:,mfc_idx);
if j == 1
subfs = extras.subfs;
end
end
c = [];
c.outsig = outsig;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
case 'osses2021'
if bRun
afb_kv = {'basef',fc,'flow',fc,'fhigh',fc,'dboffset',dBFS};
for j = 1:N_signals
[out_tmp,fc,mfc_here] = osses2021(insig(:,j),fs,afb_kv{:},afb_flags{:},ihc_flags{:},an_flags{:},mfb_flags{:});
mfc_idx = find(mfc_here<mfc_target,1,'last');
outsig(:,j) = out_tmp{1}(:,mfc_idx);
subfs = fs;
if j == 1
mfc = mfc_here(mfc_idx);
end
end
c = [];
c.outsig = outsig;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
end
if ~isempty(outsig)
switch models{k}
case {'dau1997','relanoiborra2019','osses2021'}
YL = [-100 1000];
case {'zilany2014','verhulst2015','verhulst2018','bruce2018'}
YL = [-200 500];
case 'king2019'
YL = [-.1 1]*1e-4;
end
idxi = round(ti*subfs)+1;
idxf = round(tf*subfs);
% Maximum:
[vals_ma,idx_ma] = max(outsig(idxi:idxf,:));
% min to max:
Mi = min( outsig(idxi:idxf,:) );
Ma = max( outsig(idxi:idxf,:) );
vals_ma_mi = Ma-Mi;
% this was the default:
vals_mean_hwr = mean( abs(outsig(idxi:idxf,:)) );
vals_med_fwr = median( abs(outsig(idxi:idxf,:)) );
vals_hwr = mean(max(outsig(idxi:idxf,:),0));
vals_med = (median( outsig(idxi:idxf,:) ));
vals_mean = (mean( outsig(idxi:idxf,:) ));
valsL = prctile( (outsig(idxi:idxf,:)),5);
valsU = prctile( (outsig(idxi:idxf,:)),95);
kk = 1;
MFic(k,1:N_signals,kk) = vals_ma; % figure; plot(fmods,vals); hold on
MFic_norm(k,1:N_signals,kk) = vals_ma / max(abs(vals_ma));
kk = 2;
MFic(k,1:N_signals,kk) = vals_ma_mi; % vals_mean_hwr; % figure; plot(fmods,vals); hold on
MFic_norm(k,1:N_signals,kk) = vals_ma_mi / max(abs(vals_ma_mi));
bDo = 0; % bDo = 1;
if bDo
close all
figure(100);
for iii = 1:25
subplot(1,2,1)
plot(outsig(:,iii)); ylim(YL); grid on
hold on;
plot([idxi idxi],YL,'r--');
plot([idxf idxf],YL,'r--');
title(['model: ' models{k} '-' num2str(fmods(iii))]);
hold off
subplot(1,2,2)
plot(fmods(iii),vals_ma(iii),'bo'); hold on, grid on
plot(fmods(iii),vals_mean(iii),'r>');
plot(fmods(iii),vals_mean_hwr(iii),'ks');
plot(fmods(iii),vals_ma_mi(iii),'md');
hl = legend('max','mean','mean-hwr','ma min mi'); set(hl,'box','off');
xlim([0 130])
var_here = [vals_ma vals_mean vals_mean_hwr vals_ma_mi];
ylim([min(var_here) max(var_here)])
pause(0.5);
end
end
switch L
case 30
MF_label{1} = 'a) 30 dB, max';
MF_label{2} = 'b) 30 dB, max-min';
case 70
MF_label{1} = 'c) 70 dB, max';
MF_label{2} = 'd) 70 dB, max-min';
end
end
end
for kk = 1:length(MF_label)
figure;
for k = 1:N_models
opts = {'LineStyle',LineStyle{k},'Color',Colours{k},'LineWidth',LineWidth(k)}; % ,'MarkerFaceColor','w','Markers',Markers{k},'MarkerSize',MarkersSize(k)}
plot(fmods,MFic_norm(k,:,kk),opts{:}); grid on, hold on
end
% set(gca,'Fontsize',16)
xlabel('Modulation frequency (Hz)')
ylabel('On-CF response (Normalised)')
xlim([min(fmods)-5 max(fmods)+5]);
ylim([-0.05 1.15])
Pos = get(gcf,'Position');
Pos(3:4) = [400 360]; % [550 360];
set(gcf,'Position',Pos);
if kk == 1
XTL = [];
for i = 1:length(fmods)
if mod(i,4) == 1
XTL{i} = num2str(fmods(i));
else
XTL{i} = '';
end
end
end
set(gca,'XTick',fmods(1:2:end));
set(gca,'XTickLabel',XTL(1:2:end));
% set(gca,'XTick',fmods(1:2:end));
set(gca,'YTick',-1:.1:1);
figure_handle(end+1) = gcf;
switch kk
case 1
suff_la = '';
otherwise
suff_la = ['-' num2str(kk)];
end
figure_name{end+1} = ['fig13-modulation-strength' suff_lvl suff_la];
% text(0.05,0.92,MF_label{kk},'Units','Normalized','FontSize',14,'FontWeight','Bold');
title(MF_label{kk});
end
data.figure_flag = 'do_fig13';
data.fmods = fmods;
data.MFic = MFic;
data.MFic_norm = MFic_norm;
data.models = models;
data.figure_handle = figure_handle;
data.figure_name = figure_name;
end
%% FIG 14
if flags.do_fig14
% Local script: g20191107_rerun_Verhulst2018a.m
% Generating click
lvl = 70; % lvl_dBnHL + 30;
p0=2e-5;
dur_click = 1; % 6;
N_samples = dur_click*fs;
numH = 12;
numM = 4;
numL = 4;
ic_delay_inh=0.0011; % 1.1 ms as in the manuscript
%
t=(0:1/fs:dur_click);
click_duration = (100e-6*fs); % 100 us click (Osses and Verhulst 2019 used 80 us)
% stim=zeros(length(t),1); %the simulation runs as long as the stimulus
N_length = fs/10;
sil_skip = N_length-click_duration; % 90.1 ms
samples_click = [];
samples_click_even = [];
Nr_clicks = floor(fs*dur_click/(sil_skip+click_duration));
idx_offset = round(10e-3*fs); % click starts 10 ms after time 0
for i = 1:Nr_clicks
start_sample = (i-1)*N_length+idx_offset;
if mod(i,2) == 1
samples_click = [samples_click start_sample+click_duration:start_sample+click_duration+click_duration];
else
samples_click_even = [samples_click_even start_sample+click_duration:start_sample+click_duration+click_duration];
end
end
A = 2*sqrt(2)*p0*10^(lvl/20);
insig = zeros(N_samples,1);
insig(samples_click) = A;
insig(samples_click_even) = -A;
for k = 1:N_models
%%% Loading flags and keyvals
[fg,kv] = il_get_flags(models{k});
afb_flags = fg.afb_flags;
ihc_flags = fg.ihc_flags;
an_flags = fg.an_flags;
an_keyvals = kv.an_keyvals;
mfb_flags = fg.mfb_flags;
nomfb_flags = fg.nomfb_flags;
mfb_keyvals = kv.mfb_keyvals;
%%%
fname = ['fig14_click-' models{k}];
c = amt_cache('get',fname,flags.cachemode);
if ~isempty(c)
bRun = 0;
out = c.out;
subfs = c.subfs;
mfc = c.mfc;
else
bRun = 1;
out = [];
end
mfc_target = 100;
switch models{k}
case 'dau1997'
if bRun
subfs = 20000;
afb_kv = {'subfs',subfs,'dboffset',dBFS};
t_start = tic;
[out_tmp,fc_here,mfc_here] = dau1997(insig,fs,afb_kv{:},afb_flags{:},ihc_flags{:},an_flags{:},mfb_flags{:});
out.t_elapsed = toc(t_start);
% % Adaptation loops: no time count
% % dau1997 cannot return (at this point) two output signals
% out_tmp_an = dau1997(insig,fs,afb_kv{:},afb_flags{:},ihc_flags{:},an_flags{:},nomfb_flags{:});
% out_tmp_an = fftresample(out_tmp_an,round(length(out_tmp_an)/fs*subfs)); % Resampling (as in dau1997):
mfc_idx = find(mfc_here<mfc_target,1,'last');
Nr_fc = length(fc_here);
outsig = [];
% outsig_adapt = [];
fcs = [];
for j = 1:Nr_fc
if size(out_tmp{j},2) >= mfc_idx
fcs(end+1) = fc_here(j); % only adding the fcs of filters containing mfc_idx
outsig(:,end+1) = out_tmp{j}(:,mfc_idx);
% outsig_adapt(:,end+1) = out_tmp_an(:,j);
end
end
out.fcs = fcs;
out.oustig = outsig;
out.outsig_description = 'Modulation filter bank output';
% out.outsig_adapt = outsig_adapt;
% out.outsig_adapt_description = 'Adaptation loops output';
mfc = mfc_here(mfc_idx);
c = [];
c.out = out;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
factor = 1;
unit = 'MU';
YL = [-20 560];
YT = 0:50:500;
case 'zilany2014'
if bRun
fcs = il_m2hz(401);
fcs = fcs(end:-6:1);
fcs = fcs(fcs>125);
% fcs=fcs(1:10:end); % for quick debugging only
psth_binwidth=0.0005;
kv={'fiberType',4,'numH',numH,'numM',numM,'numL',numL,'nrep',10,'psth_binwidth',psth_binwidth};
subfs = fs;
t_start = tic;
[mean_rate,psth] = zilany2014(insig,fs,fcs,kv{:});
[ic_out,~,cn_out,par] = carney2015(mean_rate,90,fs,'ic_delay_inh',ic_delay_inh);
t_elapsed = toc(t_start);
out.an(1:N_samples,:) = mean_rate(1:N_samples,:);
out.cn(1:N_samples,:) = cn_out(1:N_samples,:);
out.ic(1:N_samples,:) = ic_out(1:N_samples,:);
out.psth = psth;
out.t_elapsed = t_elapsed*ones(size(fcs))/length(fcs);
out.psth_binwidth = psth_binwidth;
out.fcs = fcs;
out.fcs_description = 'CFs that were tested';
mfc = [];
amt_disp(sprintf('Zilany2014: CN: tau_exc=%f, tan_inh=%f, D=%f, S=%f',par.tau_ex_cn,par.tau_inh_cn,par.cn_delay,par.Sinh_cn));
amt_disp(sprintf('Zilany2014: IC: tau_exc=%f, tan_inh=%f, D=%f, S=%f',par.tau_ex_ic,par.tau_inh_ic,par.ic_delay_inh,par.Sinh_ic));
out.an_all = sum(out.an,2);
out.cn_all = sum(out.cn,2);
out.ic_all = sum(out.ic,2);
out = rmfield(out,{'an','cn','ic'}); % to reduce size
c = [];
c.out = out;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
factor = 1;
unit = 'spikes/s';
YL = [-280 280];
YT = -240:40:240;
case 'verhulst2015'
if bRun
t_start = tic;
out = verhulst2015(insig,fs,'abr',afb_flags{:},ihc_flags{:},an_flags{:}, ...
kv.an_keyvals{:},mfb_flags{:});
t_elapsed = toc(t_start);
subfs = out(1).fs_abr;
out.t_elapsed = t_elapsed;
out = rmfield(out,{'v','fs_bm','ihc','anfH','anfM','anfL','an_summed','ic'});
mfc = [];
c = [];
c.out = out;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
factor = 1e6; unit = '\muV';
YL = [-.32 .32];
YT = -.3:.05:.3;
case 'verhulst2018'
if bRun
t_start = tic;
out = verhulst2018(insig,fs,'abr',afb_flags{:},ihc_flags{:},an_flags{:}, ...
kv.an_keyvals{:},mfb_flags{:});
t_elapsed = toc(t_start);
subfs = out(1).fs_abr;
out.t_elapsed = t_elapsed;
out = rmfield(out,{'v','fs_bm','ihc','anfH','anfM','anfL','an_summed','ic'});
mfc = [];
c = [];
c.out = out;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
factor = 1e6; unit = '\muV';
YL = [-.32 .32];
YT = -.3:.05:.3;
case 'bruce2018'
if bRun
fcs = il_m2hz(401);
fcs = fcs(end:-6:1);
fcs = fcs(fcs>125);
psth_binwidth=0.0005;
kv = {'numH',numH,'numM',numM,'numL',numL,'nrep',10,'psthbinwidth_mr',psth_binwidth};
% fcs=fcs(1:10:end); % for quick debugging only
tmp = bruce2018(insig,fs,fcs,kv{:});
% This is how Carney calls her model: PSTH_FT/Number_of_fibers*Model_Sampling_rate
% [ic_out,cn_out] = carney2015(tmp.psth_ft/(numH+numM+numL)*100000,90,fs,'ic_delay_inh',ic_delay_inh);
% But we also can use PSTH directly:
[ic_out,cn_out] = carney2015(tmp.psth,90,1/psth_binwidth,'ic_delay_inh',ic_delay_inh);
t_elapsed = toc(t_start);
out.t_elapsed = t_elapsed*ones(size(fcs))/length(fcs);
subfs = 1/psth_binwidth;
out.cn_all = sum(cn_out(1:round(N_samples/fs/psth_binwidth),:),2);
out.ic_all = sum(ic_out(1:round(N_samples/fs/psth_binwidth),:),2);
out.fcs = fcs;
out.fcs_description = 'CFs that were tested';
mfc = [];
c = [];
c.out = out;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
factor = 1;
unit = 'spikes/s';
YL = [-280 280];
YT = -240:40:240;
case 'king2019'
if bRun
subfs = 20000;
afb_kv = {'basef',4000,'flow',80,'fhigh',8000, ... % arbitrary
'compression_n',.3,'dboffset',dBFS,'subfs',subfs, ...
'modbank_Nmod',10}; % 10 modulation filters instead of 5
t_start = tic;
[outsig,fcs,mfc_here,step_here] = king2019(insig,fs,afb_kv{:},afb_flags{:},ihc_flags{:},an_flags{:},mfb_flags{:});
out.t_elapsed = toc(t_start);
mfc_idx = find(mfc_here<mfc_target,1,'last');
outsig = squeeze(outsig(:,:,mfc_idx));
out.fcs = fcs;
out.oustig = outsig;
out.outsig_description = 'Modulation filter bank output';
% outsig_adapt = step_here.adapted_response;
% outsig_adapt = fftresample(outsig_adapt,round(length(outsig_adapt)/fs*subfs));
%
% out.outsig_adapt = outsig_adapt;
% out.outsig_adapt_description = 'Adaptation by filtering';
mfc = mfc_here(mfc_idx);
c = [];
c.out = out;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
factor = 1e4;
unit = 'a.u. x 10^{-4}';
YL = [-0.1 2.1];
YT = [0:.2:2];
case 'relanoiborra2019'
if bRun
afb_kv = {'erbspacebw'};
t_start = tic;
% [out_tmp,fc_here,mfc_here] = relanoiborra2019_preproc(insig,fs,afb_kv{:},afb_flags{:},ihc_flags{:},an_flags{:},mfb_flags{:});
[out_tmp,mfc_here,~,fc_here] = relanoiborra2019_featureextraction(insig, fs, afb_kv{:});
out.t_elapsed = toc(t_start);
% out_tmp = [length fc mfc], i.e., [100000 60 12]
mfc_idx = find(mfc_here<mfc_target,1,'last');
Nr_fc = length(fc_here);
outsig = []; % zeros(size(out_tmp{1}(:,1)));
% outsig_adapt = [];
fcs = [];
for j = 1:Nr_fc
if size(out_tmp,3) >= mfc_idx
fcs(end+1) = fc_here(j); % only adding the fcs of filters containing mfc_idx
outsig(:,end+1) = out_tmp(:,j,mfc_idx);
% outsig_adapt(:,end+1) = out_tmp_an(:,j);
end
end
out.fcs = fcs;
out.oustig = outsig;
out.outsig_description = 'Modulation filter bank output';
% out.outsig_adapt = outsig_adapt;
% out.outsig_adapt_description = 'Adaptation loops output';
mfc = mfc_here(mfc_idx);
c = [];
c.out = out;
c.subfs = fs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
factor = 1;
unit = 'MU';
YL = [-20 560];
YT = 0:50:500;
case 'osses2021'
if bRun
subfs = 20000;
afb_kv = {'subfs',subfs,'dboffset',dBFS};
t_start = tic;
[out_tmp,fc_here,mfc_here] = osses2021(insig,fs,afb_kv{:},afb_flags{:},ihc_flags{:},an_flags{:},mfb_flags{:});
out.t_elapsed = toc(t_start);
mfc_idx = find(mfc_here<mfc_target,1,'last');
Nr_fc = length(fc_here);
outsig = [];
fcs = [];
for j = 1:Nr_fc
if size(out_tmp{j},2) >= mfc_idx
fcs(end+1) = fc_here(j); % only adding the fcs of filters containing mfc_idx
outsig(:,end+1) = out_tmp{j}(:,mfc_idx);
end
end
out.fcs = fcs;
out.oustig = outsig;
out.outsig_description = 'Modulation filter bank output';
mfc = mfc_here(mfc_idx);
c = [];
c.out = out;
c.subfs = subfs;
c.mfc = mfc;
amt_cache('set',fname,c);
end
factor = 1;
unit = 'MU';
YL = [-20 560];
YT = 0:50:500;
end
if ~isempty(out)
w5 = [];
switch models{k}
case {'dau1997','king2019','relanoiborra2019','osses2021'}
num_cfs = length(out.fcs);
w5 = sum(out.oustig,2)/num_cfs;
% w3 = zeros(size(w5)); % no comparable to w3
% w1 = sum(out.outsig_adapt,2)/num_cfs;
case {'zilany2014','bruce2018'}
num_cfs = length(out.fcs);
% w1 = out.an_all/num_cfs; w3 = out.cn_all/num_cfs;
w5 = out.ic_all/num_cfs;
case {'verhulst2015','verhulst2018'}
% w1 = out.w1; w3 = out.w3;
w5 = out.w5;
end
% -------------------------------------------------------------
% Time elapsed:
if length(out.t_elapsed) ~= 1
t_elapsed_here = sum(out.t_elapsed);
else
t_elapsed_here = out.t_elapsed;
end
t_elapsed(1,k) = t_elapsed_here;
t_elapsed(2,k) = num_cfs;
t_elapsed(3,k) = t_elapsed(1,k)/num_cfs;
if k == 1
t_elapsed_description = 'Row 1: Total time elapsed (s); Row 2: Total number of simulated channels; Row 3 = time per channel (Row 1/Row 2)';
end
fprintf('Model: %s; time elapsed=%.3f s (%.4f s per channel, %.0f channels)\n',models{k},t_elapsed(1,k),t_elapsed(3,k),t_elapsed(2,k));
% END Time elapsed --------------------------------------------
t_ms = 1000*(1:length(w5))/subfs;
disp('Using Wave-V estimate only...')
efr_here = w5;
figure; % For each model there is one new figure
figure_handle(end+1) = gcf;
figure_name{end+1} = ['fig14-click-' models{k}];
opts = {'LineStyle','-','Color',Colours{k},'LineWidth',LineWidth(k)};
% if k == 1
% warning('bReshape is temporal...')
% end
t_ms_orig = t_ms;
%%% Getting the clicks to be plotted only
idxs = [1 2 9 10]; % Click numbers to be plotted
N = length(efr_here)/Nr_clicks;
M = Nr_clicks;
efr_here = reshape(efr_here,N,M);
t_ms_orig = t_ms;
t_ms = reshape(t_ms ,N,M);
efr_here = efr_here(:,idxs);
Nr_clicks_here = length(idxs);
t_ms = t_ms(:,idxs);
efr_here = efr_here(:); % truncated clicks back to a one-column array
%%%
pl(k) = plot(t_ms_orig(1:length(efr_here)),factor*efr_here,opts{:}); hold on, grid on
title(models{k})
xlabel('Time (ms)');
step_time = 40; % 30
idxi = 210;
idxf = idxi + 180;
XT = [10:step_time:170 idxi:step_time:idxf];
idxi = floor(t_ms(1,3));
idxf = idxi + 180;
XT_for_tick = [10:step_time:170 idxi:step_time:idxf];
XTL = [];
for ii = 1:length(XT)
if mod(ii,2) == 1
XTL{ii} = num2str(XT_for_tick(ii));
else
XTL{ii} = '';
end
end
set(gca,'XTick' ,XT);
set(gca,'XTickLabel',XTL);
xlim([-5 390]);
ylim(YL);
YTL = [];
for ii = 1:length(YT)
if mod(ii,2) == 1
YTL{ii} = num2str(YT(ii));
else
YTL{ii} = '';
end
end
set(gca,'YTick',YT);
set(gca,'YTickLabel',YTL);
% ylabel(['Amplitude (' unit ')']);
ylabel(['(' unit ')']);
Pos = get(gcf,'Position');
Pos(3:4) = [380 300];
set(gcf,'Position',Pos);
YL = get(gca,'YLim');
plot(200*[1 1],YL,'k-');
text(0.05,.92,sprintf('Clicks #%.0f-%.0f',idxs(1:2)),'Units','Normalized','FontSize',14,'FontWeight','Bold');
text(0.55,.92,sprintf('Clicks #%.0f-%.0f',idxs(3:4)),'Units','Normalized','FontSize',14,'FontWeight','Bold');
end % end ~ifempty(out)
Nr_samples = length(efr_here);
output_buf = reshape(efr_here,round(Nr_samples/Nr_clicks_here),Nr_clicks_here);
Amp_max(k,:) = max(output_buf);
Amp_min(k,:) = min(output_buf);
end % end for k
data.Amp_max = Amp_max;
data.Amp_min = Amp_min;
data.Amp_pp = Amp_max - Amp_min;
data.models = models;
data.figure_flag = 'do_fig14';
data.figure_handle = figure_handle;
data.figure_name = figure_name;
end
%%% End of file exp_osses2021.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Start of subfunctions:
function [flags,keyvals] = il_get_flags(model_str)
kSR_H = 68.5; % spikes/s, spontaneous rate: only Verhulst 2018
kSR_M = 10; % spikes/s, spontaneous rate: Verhulst 2015 and 2018
kSR_L = 1; % spikes/s, spontaneous rate: Verhulst 2015 and 2018
numH = 12;
numM = 4;
numL = 4;
bAMT = 1; % Is AMT v1.0
switch model_str
case 'dau1997'
fc_flags = [];
afb_flags = {};
afb_keyvals = [];
ihc_flags = {'ihc','ihc_dau1996'};
noihc_flags = {'no_ihc'};
an_flags = {'adt','adt_dau1997'};
noan_flags = {'no_adt','no_mfb'};
an_keyvals = [];
mfb_flags = {'mfb','mfb_dau1997'};
nomfb_flags = {'no_mfb'};
mfb_keyvals = [];
case 'osses2021'
fc_flags = [];
afb_flags = {'afb_osses2021'};
afb_keyvals = [];
ihc_flags = {'ihc','ihc_breebaart2001'};
noihc_flags = {'no_ihc'};
an_flags = {'adt', 'adt_osses2021'};
noan_flags = {'no_adt','no_mfb'};
an_keyvals = [];
mfb_flags = {'mfb','mfb_jepsen2008'};
nomfb_flags = {'no_mfb'};
mfb_keyvals = [];
case 'relanoiborra2019'
fc_flags = [];
afb_flags = {'no_internalnoise','erbspacebw'};
afb_keyvals = [];
ihc_flags = {'ihc','ihc_relanoiborra2019'};
noihc_flags = {'no_ihc'};
an_flags = {'adt', 'adt_relanoiborra2019'};
noan_flags = {'no_adt','no_mfb'};
an_keyvals = [];
mfb_flags = {'mfb','mfb_jepsen2008'};
nomfb_flags = {'no_mfb'};
mfb_keyvals = [];
case 'king2019'
fc_flags = [];
afb_flags = {'afb','compression_brokenstick'};
afb_keyvals = {'compression_n',0.3};
ihc_flags = {'ihc'};
noihc_flags = {'no_ihc'};
an_flags = {'adt'};
noan_flags = {'no_adt','no_mfb'};
an_keyvals = [];
mfb_flags = {'mfb'};
nomfb_flags = {'no_mfb'};
mfb_keyvals = [];
case 'verhulst2015'
fc_flags = {'abr'}; % abr = 401 frequency channels
afb_flags = {'no_outerear','middleear'}; % these are the defaults
afb_keyvals = [];
ihc_flags = {'ihc'}; % this is the default
noihc_flags = {'no_ihc'};
an_flags = {'an'};
noan_flags = {'no_an','no_cn','no_ic'}; % if no_an, then no_cn and no_ic
an_keyvals = {'numH',numH,'numM',numM,'numL',numL,'kSR_H',kSR_H,'kSR_M',kSR_M,'kSR_L',kSR_L};
mfb_flags = {'no_cn','ic'};
nomfb_flags = {'no_cn','no_ic'};
mfb_keyvals = [];
case 'verhulst2018'
fc_flags = {'abr'}; % abr = 401 frequency channels
afb_flags = {'no_outerear','middleear'}; % these are the defaults
afb_keyvals = [];
ihc_flags = {'ihc'}; % this is the default
noihc_flags = {'no_ihc'};
an_flags = {'an'};
noan_flags = {'no_an','no_cn','no_ic'};
an_keyvals = {'numH',numH,'numM',numM,'numL',numL,'kSR_H',kSR_H,'kSR_M',kSR_M,'kSR_L',kSR_L};
mfb_flags = {'no_cn','ic'};
nomfb_flags = {'no_cn','no_ic'};
mfb_keyvals = [];
case 'zilany2014'
species = 'human';
noiseType = 'fixedFGn';
% noiseType = 'varFGn';
fc_flags = [];
if bAMT
afb_flags = {species};
else
afb_flags = {'middleear',species}; % this is the default, making sure that 'species' is always loaded
end
afb_keyvals = [];
ihc_flags = {'ihc'}; % this is the default
noihc_flags = {'no_ihc'};
an_flags = {'an',species,noiseType};
if numH ~= 0
an_flags(end+1) = {'anfH'};
end
if numM ~= 0
an_flags(end+1) = {'anfM'};
end
if numL ~= 0
an_flags(end+1) = {'anfL'};
end
noan_flags = {'no_an',species,noiseType};
an_keyvals = {'numH',numH,'numM',numM,'numL',numL,'kSR_H',kSR_H,'kSR_M',kSR_M,'kSR_L',kSR_L, ...
'psth_binwidth',0.5e-3};
mfb_flags = {'cn','ic'};
nomfb_flags = {'no_cn','no_ic'};
mfb_keyvals = {'BMF',90,'apply_ic_hwr',0};
case 'bruce2018'
species = 'human';
noiseType = 'fixedFGn';
% noiseType = 'varFGn';
fc_flags = [];
if bAMT
afb_flags = {species};
else
afb_flags = {'middleear',species}; % this is the default, making sure that 'species' is always loaded
end
afb_keyvals = [];
ihc_flags = {'ihc'}; % this is the default
noihc_flags = {'no_ihc'};
an_flags = {'an',species,noiseType};
if numH ~= 0
an_flags(end+1) = {'anfH'};
end
if numM ~= 0
an_flags(end+1) = {'anfM'};
end
if numL ~= 0
an_flags(end+1) = {'anfL'};
end
noan_flags = {'no_an',species,noiseType};
an_keyvals = {'numH',numH,'numM',numM,'numL',numL,'kSR_H',kSR_H,'kSR_M',kSR_M,'kSR_L',kSR_L, ...
'psth_binwidth',0.5e-3};
mfb_flags = {'cn','ic'};
nomfb_flags = {'no_cn','no_ic'};
mfb_keyvals = {'BMF',90,'apply_ic_hwr',0};
end
flags = [];
flags.fc_flags = fc_flags;
flags.afb_flags = afb_flags;
flags.ihc_flags = ihc_flags;
flags.noihc_flags = noihc_flags;
flags.an_flags = an_flags;
flags.noan_flags = noan_flags;
flags.mfb_flags = mfb_flags;
flags.nomfb_flags= nomfb_flags;
keyvals = [];
keyvals.afb_keyvals = afb_keyvals;
keyvals.an_keyvals = an_keyvals;
keyvals.mfb_keyvals = mfb_keyvals;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function rms_val = il_rmsdb(insig)
rms_val = 20*log10(rms(insig));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [ac_target,dc_target,vrest] = il_get_ac_dc_osses2022(ihc_target,ac_reg,dc_reg)
% function [ac_target,dc_target,vrest] = il_get_ac_dc_osses2022(ihc_target,ac_reg,dc_reg)
%
% DC: is computed from the signal (mean value using the ac_reg samples), and
% then this value is referenced to the resting potential
% AC: I compute it here as the peak-to-peak voltage, in line with Russel and
% Palmer 1986
vrest = median(ihc_target(dc_reg,:)); % median of the silent initial segment
dc_target = mean(ihc_target(ac_reg,:))-vrest;
v_min = min(ihc_target(ac_reg,:));
v_max = max(ihc_target(ac_reg,:));
dist_ac_pp = v_max-v_min; % peak to peak
ac_target = dist_ac_pp; % approximation to the RMS of the AC
if nargout == 0
t_ds = 1:size(ihc_target,1);
for j = 1:size(ihc_target,2);
figure;
plot(t_ds,ihc_target(:,j)); hold on;
plot(t_ds(dc_reg),ihc_target(dc_reg,j),'r');
dc2plot = [vrest(j) vrest(j)+dc_target(j)];
plot(t_ds(dc_reg(end))*[1 1],dc2plot,'r');
plot([min(t_ds) max(t_ds)],vrest(j)*[1 1],'r--','LineWidth',2);
plot(t_ds(ac_reg),ihc_target(ac_reg,j),'m-');
ac2plot = (v_min(j)+dist_ac_pp(j)/2)*[1 1];
plot(t_ds([ac_reg(1) ac_reg(end)]),ac2plot,'k--','LineWidth',2);
plot(t_ds([ac_reg(1000) ac_reg(1000)]),dc2plot,'k-');
xlabel('Time (samples)');
ylabel('IHC receptor potential (V)');
title(sprintf('Signal nr. %.0f Hz \n(AC=%.4f; DC=%.4f; ratio=%.4f)',j, ...
dc_target(j),ac_target(j),ac_target(j)/dc_target(j)));
legend('IHC response','DC component','AC component');
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [f,x] = il_m2hz(Nr_sections,k)
% function [f,x] = il_m2hz(Nr_sections,k)
%
% 1. Description:
% See Greenwood 1990, Equation 1 with A = 165.4, k = 0.85.
% bApex_to_base is referenced to Helicotrema.
%
% Programmed by Alejandro Osses, WAVES, UGent, Belgium, 2018-2020
if nargin < 2
k = 0.85; % As used in the models by Verhulst et al
end
if nargin == 0
Nr_sections = 500;
end
cochleaLength = 0.035; % m
helicotremaLength = 0.001; % m
A = 165.4118; % For human specie
a = 61.765; %
bm_length = cochleaLength-helicotremaLength;
switch Nr_sections
case {201,401}
% Nr_sections = 500;
f_range = [12000 112];
step_bm = bm_length/500;
otherwise
f_range = [];
step_bm = bm_length/Nr_sections;
end
A0 = 20682; % cochlear_model2018.py, L114
switch Nr_sections
case 201
x = step_bm :2*step_bm:bm_length;
case 401
x = step_bm :step_bm:bm_length;
case 500
x = step_bm/2:step_bm:bm_length;
case 1000
x = step_bm :step_bm:bm_length;
otherwise
error('Check this function: %s',mfilename);
end
f = A0*(10.^(-a*x)) - A*k;
if ~isempty(f_range)
idxi = find(f>= f_range(1),1,'last');
idxf = find(f>= f_range(2),1,'last');
f = f(idxi:idxf);
x = x(idxi:idxf);
end
if nargout == 0
fprintf('The output CF derived from %.0f cochlear sections with frequencies between %.1f and %.1f [Hz]\n',length(f),f(1),f(end));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function col_rgb = il_rgb(colour)
switch colour
case 'Gray'
col_rgb = [0.5 0.5 0.5];
case 'LightGray'
col_rgb = [0.8242 0.8242 0.8242];
case 'Green'
col_rgb = [0 0.5 0];
case 'LightSkyBlue'
col_rgb = [0.5273 0.8047 0.9792];
case 'Maroon'
col_rgb = [0.5 0 0];
case 'mediumorchid'
col_rgb = [0.7266 0.3320 0.8242];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [env,idx_env] = il_Get_envelope2(insig,me)
method = 2;
switch method
case 1
error('Not used, tested on 7/4/2021')
case 2
% bDebug = 0;
% if bDebug
% plot(insig); hold on
% end
env = [];
idx_env = [];
if nargin < 4
me = mean(insig); % prctile(insig,75);
end
L1 = [1:length(insig); insig'];
L2 = [1 length(insig); me me];
P = il_InterX(L1,L2);
N_P = size(P,2);
% if bDebug
% YL = get(gca,'YLim');
% for j = 1:N_P
% plot(round(P(1,j))*[1 1],YL,'k-');
% end
% end
for j = 1:2:N_P-2
idx1 = round(P(1,j));
idx2 = round(P(1,j+1));
[env(end+1),idx_here] = max(insig(idx1:idx2));
idx_env(end+1) = idx_here+idx1-1;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [BW_ERB, Q_ERB, extra]= il_Get_ERB_estimation(impulse_ch, CF, fs)
N = length(impulse_ch); % N-point FFT
K = floor(N/2); % K-non redundant points
freq_here = (1:K)*(fs/2)/K;
Amp = (2*abs(fft(impulse_ch,N))/N).^2; Amp = Amp(:);
[M,Mn] = max(Amp(1:K));
E = sum(Amp(1:K));
BW_ERB = (E/M)*fs/N;
Q_ERB = CF/BW_ERB;
Amp_dB = 10*log10(Amp(1:K));
Amp_dB = Amp_dB-max(Amp_dB);
L1 = [freq_here; transpose(Amp_dB)];
L2 = [min(freq_here) max(freq_here); [-10 -10]];
P = il_InterX(L1, L2);
if ~isempty(P) && size(P,1)==2
flow_10 = P(1,1);
fhigh_10 = P(1,2);
BW10 = P(1,2)-P(1,1);
Q10 = CF/BW10;
else
flow_10 = nan;
fhigh_10 = nan;
BW10 = nan;
Q10 = nan;
end
L2 = [min(freq_here) max(freq_here); [-3 -3]];
P = il_InterX(L1, L2);
if ~isempty(P) && size(P,1)==2
flow_03 = P(1,1);
fhigh_03 = P(1,2);
BW03 = P(1,2)-P(1,1);
Q03 = CF/BW03;
else
flow_03 = nan;
fhigh_03 = nan;
BW03 = nan;
Q03 = nan;
end
extra.BW_ERB = BW_ERB;
extra.BW10 = BW10;
extra.BW03 = BW03;
extra.Q_ERB = Q_ERB;
extra.Q10 = Q10;
extra.Q03 = Q03;
extra.flow_03 = flow_03;
extra.flow_10 = flow_10;
extra.fhigh_03 = fhigh_03;
extra.fhigh_10 = fhigh_10;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function P = il_InterX(L1,L2)
%IL_INTERX Intersection of curves
% P = IL_INTERX(L1,L2) returns the intersection points of two curves L1
% and L2. The curves L1,L2 can be either closed or open and are described
% by two-row-matrices, where each row contains its x- and y- coordinates.
%
% P has the same structure as L1 and L2, and its rows correspond to the
% x- and y- coordinates of the intersection points of L1 and L2. If no
% intersections are found, the returned P is empty.
%
% Two words about the algorithm: Most of the code is self-explanatory.
% The only trick lies in the calculation of C1 and C2. To be brief, this
% is essentially the two-dimensional analog of the condition that needs
% to be satisfied by a function F(x) that has a zero in the interval
% [a,b], namely
% F(a)*F(b) <= 0
% C1 and C2 exactly do this for each segment of curves 1 and 2
% respectively. If this condition is satisfied simultaneously for two
% segments then we know that they will cross at some point.
% Each factor of the 'C' arrays is essentially a matrix containing
% the numerators of the signed distances between points of one curve
% and line segments of the other.
%
% This function is based on InterX.m (v3.0, 21 Sept. 2010) by author 'NS'
% that is available within the Mathworks FileExchange.
% Reordering the data before intersecting L1 and L2:
x1 = L1(1,:)'; x2 = L2(1,:);
y1 = L1(2,:)'; y2 = L2(2,:);
dx1 = diff(x1); dy1 = diff(y1);
dx2 = diff(x2); dy2 = diff(y2);
%...Determine 'signed distances'
S1 = dx1.*y1(1:end-1) - dy1.*x1(1:end-1);
S2 = dx2.*y2(1:end-1) - dy2.*x2(1:end-1);
C1 = le(il_D(bsxfun(@times,dx1,y2)-bsxfun(@times,dy1,x2),S1),0);
C2 = le(il_D((bsxfun(@times,y1,dx2)-bsxfun(@times,x1,dy2))',S2'),0)';
%...Obtain the segments where an intersection is expected
[i,j] = find(C1 & C2);
if isempty(i),P = zeros(2,0);return; end;
%...Transpose and prepare for output
i=i'; dx2=dx2'; dy2=dy2'; S2 = S2';
L = dy2(j).*dx1(i) - dy1(i).*dx2(j);
i = i(L~=0); j=j(L~=0); L=L(L~=0); %...Avoid divisions by 0
%...Solve system of eqs to get the common points
P = unique([dx2(j).*S1(i) - dx1(i).*S2(j), ...
dy2(j).*S1(i) - dy1(i).*S2(j)]./[L L],'rows')';
function u = il_D(x,y)
u = bsxfun(@minus,x(:,1:end-1),y).*bsxfun(@minus,x(:,2:end),y);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [waveform,freq_array] = il_Profile_Analysis(dur, rampdur, ncomponents, dB_incr, stim_dB, Fs, freq_array)
% function [waveform,freq_array] = il_Profile_Analysis(dur, rampdur, ncomponents, dB_incr, stim_dB, Fs, freq_array)
%
% This function produces a vector of log-spaced components based on Lentz (JASA 2005)
%Variables:
% dur = duration in sec (e.g. 0.5 sec)
% ncomponents is # of components in stimulus (spaced between 200 & 5000 Hz)
% dB_incr = 20*log(Delta_A/A), where A is the amplitude of the standard component at 1000 Hz
% ramp_time: onset/offset in seconds
% stim_dB = overall stimulus level in dB SPL (both inetervals are scaled to same dB SPL)
% Fs = sampling rate (Hz)
npts = dur * Fs; % # pts in stimulus
t = (0:(npts-1))/Fs; % time vector
if nargin < 7
freq_array = logspace(log10(200),log10(5000),ncomponents); %column vector of n equally spaced compenents in the frequency range 200 to 5000Hz
end
waveform = 0; % initialize variable
for f = freq_array % step through each frequency component in the complex
phase = 2*pi * rand(1,1); %Randomly vary the starting phase of each component
if mod(f,4) ~= 0 %rounding each component to the nearest 4Hz (see Lentz, 2005)
freq = 4*(ceil(f/4));
else
freq = f;
end
% Note that the increment is a tone added in phase to the component at 1000 Hz
incr_size = 10.^(dB_incr/20); % convert increment from dB into a linear scalar (if dB_incr = 0, incr_size = 1 and the amplitude at 1000 Hz is doubled)
%Adding components with or without incr
if freq == 1000
waveform = waveform + (1 + incr_size) * cos(2 * pi * freq * t + phase);
else
waveform = waveform + cos(2 * pi * freq * t + phase);
end
end
waveform = tukeywin(npts, 2*rampdur/dur)' .* waveform; % gate
waveform = 20e-6 * 10.^(stim_dB/20) * waveform/rms(waveform);% convert signal into Pascals