This documentation page applies to an outdated major AMT version. We show it for archival purposes only.
Click here for the documentation menu and here to download the latest AMT (1.6.0).
function varargout = baumgartner2016( target,template,varargin )
%BAUMGARTNER2016 Level-dependent model for localization in sagittal planes
% Usage: [p,rang,tang] = baumgartner2016( target,template )
% [err,pred,m] = baumgartner2016( target,template,errorflag )
%
% Input parameters:
% target : binaural impulse response(s) referring to the directional
% transfer function(s) (DFTs) of the target sound(s).
% template: binaural impulse responses of all available
% listener-specific DTFs of the sagittal plane referring to
% the perceived lateral angle of the target sound
% label: 2-element cell array including labels used for caching.
% Provide listener ID (e.g., 'NH12') in label{1}, and
% target condition information in label{2}.
%
% Output parameters:
% p : predicted probability mass vectors for response angles
% with respect to target positions
% 1st dim: response angle
% 2nd dim: target angle
% rang : polar response angles (after regularization of angular
% sampling)
% tang : polar target angles (usefull if sagittal-plane HRTFs are
% extracted directly from SOFA object)
% err : predicted localization error (acc. to performance measure
% defined in errorflag*
% pred : structure with fields p, rang, tang*
% m : item list from virtual experiment. See
% help localizationerror for format description.
%
% BAUMGARTNER2016(...) is a model for sound-source localization
% in sagittal planes (SPs). It bases on the comparison of internal sound
% representation with a template and results in a probabilistic
% prediction of polar angle response.
%
% BAUMGARTNER2016 accepts the following optional parameters:
%
% 'ID' Listeners ID (important for caching).
%
% 'Condition' Label of experimental condition (also for caching).
%
% 'fs',fs Define the sampling rate of the impulse responses.
% Default value is 48000 Hz.
%
% 'S',S Set the listener-specific sensitivity threshold
% (threshold of the sigmoid link function representing
% the psychometric link between transformation from the
% distance metric and similarity index) to S.
% Default value is 1.
%
% 'lat',lat Set the apparent lateral angle of the target sound to
% lat. Default value is 0 degree (median SP).
%
% 'stim' Define the stimulus (source signal without directional
% features). As default temstim is used.
%
% 'fsstim' Define the sampling rate of the stimulus.
% Default value is 48000 Hz.
%
% 'temstim' Define the dummy stimulus used to create the templates.
% The default is Gaussian white noise with a duration of 170 ms.
%
% 'SPL',L Set the SPL of the stimulus to L dB.
% Default value is 60dB.
%
% 'SPLtem',Lt Set the SPL of the templates to a specific SPL of Lt*dB
% if Lt is a scalar or define a SPL range between
% Lt(1) and Lt(2)*dB if Lt is a two-element vector.
% Default range is 40 to 70dB.
%
% 'flow',flow Set the lowest frequency in the filterbank to
% flow. Default value is 700 Hz.
%
% 'fhigh',fhigh Set the highest frequency in the filterbank to
% fhigh. Default value is 18000 Hz.
%
% 'space',sp Set spacing of auditory filter bands (i.e., distance
% between neighbouring bands) to sp in number of
% equivalent rectangular bandwidths (ERBs).
% Default value is 1 ERB.
%
% 'do',do Set the differential order of the spectral gradient
% extraction to do. Default value is 1 and includes
% restriction to positive gradients inspired by cat DCN
% functionality.
%
% 'bwcoef',bwc Set the binaural weighting coefficient bwc.
% Default value is 13 degrees.
%
% 'polsamp',ps Define the the polar angular sampling of the current
% sagittal plane. As default the sampling of ARIs HRTF
% format at the median SP is used, i.e.,
% ps = [-30:5:70,80,100,110:5:210] degrees.
%
% 'mrsmsp',mrs Set the motoric response scatter mrs within the median
% sagittal plane. Default value is 17 degrees.
%
% 'cohc',cohc OHC scaling factor: 1 denotes normal OHC function (default);
% 0 denotes complete OHC dysfunction.
%
% 'cihc',cihc IHC scaling factor: 1 denotes normal IHC function (default);
% 0 denotes complete IHC dysfunction.
%
% 'fiberTypes',fT Types of the fibers based on spontaneous rate (SR) in
% spikes/s: fT=1 for Low SR; fT=2 for Medium SR;
% fT=3 for High SR. Default is fT = 1:3.
%
% BAUMGARTNER2016 accepts the following flags:
%
% 'zilany2014' Use the model from Zilany et al. (2009,2014) for spectral
% analysis. This is the default.
%
% 'gammatone' Use the Gammatone filterbank for spectral analysis.
%
% 'SPLtemAdapt' Set SPL of templates acc. to target (*Lt*=*L*).
%
% 'NHtem' No adaptation of templates to hearing impairment,
% i.e., templates are processed with cohc=cihc=1 and
% fT = 1:3.
%
% 'ihc' Incorporate the transduction model of inner hair
% cells used by Dau et al. (1996).
%
% 'noihc' Do not incorporate the IHC stage. This is the default.
%
% 'regular' Apply spline interpolation in order to regularize the
% angular sampling of the polar response angle.
% This is the default.
%
% 'noregular' Disable regularization of angular sampling.
%
% 'errorflag' May be one of the error flags defined in
% baumgartner2014_pmv2ppp or localizationerror.
%
% 'redoSpectralAnalysis' Flag to redo also spectral analysis based on
% zilany2014 model.
%
% Requirements:
% -------------
%
% 1) SOFA API from http://sourceforge.net/projects/sofacoustics for Matlab (in e.g. thirdparty/SOFA)
%
% 2) Data in hrtf/baumgartner2016
%
%
% See also: data_baumgartner2016,
% exp_baumgartner2016, baumgartner2016_calibration,
% baumgartner2014_pmv2ppp,
% baumgartner2014_virtualexp, localizationerror,
% baumgartner2016_spectralanalysis
%
% References:
% R. Baumgartner, P. Majdak, and B. Laback. Modeling the effects of
% sensorineural hearing loss on auditory localization in the median
% plane. Trends in Hearing, 20:1-11, 2016.
%
% M. S. A. Zilany, I. C. Bruce, and L. H. Carney. Updated parameters and
% expanded simulation options for a model of the auditory periphery. The
% Journal of the Acoustical Society of America, 135(1):283-286, Jan.
% 2014.
%
%
% Url: http://amtoolbox.sourceforge.net/amt-0.9.9/doc/models/baumgartner2016.php
% Copyright (C) 2009-2015 Piotr Majdak and the AMT team.
% This file is part of Auditory Modeling Toolbox (AMT) version 0.9.9
%
% 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/>.
% AUTHOR: Robert Baumgartner, Acoustics Research Institute, Vienna, Austria
%% Check input options
definput.import={'baumgartner2016'};
posdepnames = {'fs','S','lat','stim','fsstim'};
[flags,kv]=ltfatarghelper(posdepnames,definput,varargin);
% Check default condition label for short stimuli
if length(kv.stim)/kv.fsstim < 0.005 && strcmp(kv.Condition,'Long') % short stimulus
kv.Condition = '';
end
% Extract sagittal-plane HRTFs
if isstruct(target) % Targets given in SOFA format
kv.fs = target.Data.SamplingRate;
[target,tang] = extractsp( kv.lat,target );
end
if isstruct(template) % Template given in SOFA format
[template,kv.polsamp] = extractsp( kv.lat,template );
end
%% Error handling
if size(template,2) ~= length(kv.polsamp)
fprintf('\n Error: Second dimension of template and length of polsamp need to be of the same size! \n')
return
end
%% Stimulus
% flags.temstim = false;
if isempty(kv.stim)
kv.stim = kv.temstim;
% flags.temstim = true;
kv.fsstim = kv.fs;
elseif isempty(kv.fsstim)
kv.fsstim = kv.fs;
end
if flags.do_headphone% || flags.do_drnl
hpfilt = headphonefilter(kv.fs);
kv.stim = lconv(kv.stim,hpfilt(:));
end
%% DTF filtering
if ~isequal(kv.fs,kv.fsstim)
amt_disp('Sorry, sampling rate of stimulus and HRIRs must be the same!')
return
end
tmp = lconv(target,kv.stim);
target = reshape(tmp,[size(tmp,1),size(target,2),size(target,3)]); % workaround for lconv bug
tmp = lconv(template,kv.temstim);
template = reshape(tmp,[size(tmp,1),size(template,2),size(template,3)]); % workaround for lconv bug
%% Cochlear filter bank -> internal representations
if flags.do_redoSpectralAnalysis
redoSAflag = 'redo';
else
redoSAflag = 'normal';
end
% Target profile
[mreptar,fc] = baumgartner2016_spectralanalysis(target,kv.SPL,'target',...
'argimport',flags,kv,redoSAflag);
% Template profile
if flags.do_NHtem
kv.cohc = 1;
kv.cihc = 1;
kv.fiberTypes = 1:3;
end
if flags.do_SPLtemAdapt
kv.SPLtem = kv.SPL;
end
if isscalar(kv.SPLtem) % all templates represented at a fixed SPL
mreptem = baumgartner2016_spectralanalysis(template,kv.SPLtem,'template',...
'argimport',flags,kv,redoSAflag);
else % average across SPL range
mreptem = baumgartner2016_spectralanalysis(template,kv.SPLtem(1),'template',...
'argimport',flags,kv,redoSAflag);
SPLtemRange = kv.SPLtem(1):10:kv.SPLtem(2);
for ii = 2:length(SPLtemRange)
mreptem = mreptem + ...
baumgartner2016_spectralanalysis(template,SPLtemRange(ii),'template',...
'argimport',flags,kv,redoSAflag);
end
mreptem = mreptem/length(SPLtemRange);
end
%% Positive spectral gradient extraction
if kv.do == 1 && flags.do_psge
% duration-dependence of c2 (inhibitory strength)
if length(kv.stim)/kv.fs < 5e-3 % halfen if shorter than 5ms
c2 = kv.psgeshort;
else
c2 = 1;
end
if flags.do_gammatone
greptar = baumgartner2014_gradientextraction(mreptar,fc,c2);
greptem = baumgartner2014_gradientextraction(mreptem,fc);
else % zilany
greptar = baumgartner2016_gradientextraction(mreptar,fc,'argimport',flags,kv);
greptem = baumgartner2016_gradientextraction(mreptem,fc,'argimport',flags,kv);
end
else
amt_disp('Cue extraction different to baumgartner2014','progress')
if kv.do == 1 && flags.do_dcn% DCN inspired feature extraction
for ch = 1:size(mreptar,3)
greptem(:,:,ch) = dcn(mreptem(:,:,ch),fc);
greptar(:,:,ch) = dcn(mreptar(:,:,ch),fc);
end
elseif kv.do == 2 % proposed by Zakarauskas & Cynader (1993)
greptem = diff(mreptem,kv.do);
greptar = diff(mreptar,kv.do);
else
greptem = mreptem;
greptar = mreptar;
end
end
%% Comparison process
if flags.do_isd && not(flags.do_intensityweighting) && not(flags.do_diff)
if flags.do_gammatone
sigma = baumgartner2014_comparisonprocess(greptar,greptem);
else % zilany
sigma = baumgartner2016_comparisonprocess(greptar,greptem);
end
else
amt_disp('Comparison process different to baumgartner2014','progress')
if flags.do_diff
greptar = diff(greptar);
greptem = diff(greptem);
end
sigma=zeros(size(mreptem,2),size(mreptar,2),size(mreptem,3)); % init
for ch = 1:size(mreptar,3)
for it = 1:size(mreptar,2)
if flags.do_isd
isd = repmat(greptar(:,it,ch),[1,size(greptem(:,:,ch),2),1]) - greptem(:,:,ch);
if kv.do == 0
sigma(:,it,ch) = sqrt(squeeze(var(isd))); % standard dev. across frequencies (Middlebrooks, 1999)
else
if isnan(nanmean(abs(isd)))
sigma(:,it,ch) = 0;
else
if flags.do_intensityweighting
Ifw = mreptar(:,it,ch)/max(mreptar(:,it,ch));
isd = isd.*repmat(Ifw,1,size(isd,2));
end
sigma(:,it,ch) = nanmean(abs(isd)); % L1-norm across frequencies
end
end
elseif flags.do_corr
if sum(greptar(:,it,ch)==0) == length(greptar(:,it,ch))
sigma(:,it,ch) = 0;
else
r = corrcoef([greptar(:,it,ch) greptem(:,:,ch)]); % in case of NAN use flag: 'rows','pairwise' (but very slow!!!)
sigma(:,it,ch) = r(1,2:end);
end
end
end
end
end
%% OPTIMAL FT SELECTION
Ntang = size(mreptar,2);
if flags.do_ftopt
% Var 1: Winner takes it all
% si = max(si_ft,[],4);
% Var 2: Select for each target the SI distribution of the fiber type
% yielding the minimum internal distance metric (sigma)
if length(kv.fiberTypes) == 3
sigma_ft = sigma;
sigma = sigma_ft(:,:,:,1,:); % init with ft=1
N = zeros(Ntang * size(mreptar,3),3);
N(:,1) = 1;
for ch = 1:size(mreptar,3)
for it = 1:Ntang
for ft = 2:3
if min(sigma_ft(:,it,ch,ft,:)) < min(sigma(:,it,ch,:,:))
sigma(:,it,ch,:,:) = sigma_ft(:,it,ch,ft,:);
N(it+(ch-1)*Ntang,ft) = 1;
end
end
end
end
N(:,2) = max(N(:,2) - N(:,3),0);
N(:,1) = N(:,1) - (N(:,2)+N(:,3));
N = sum(N);
fileID = fopen(fullfile(amt_basepath,'modelstages','baumgartner2016_fiberTypeCounter'),'a');
fprintf(fileID,'%i, %i, %i\n',N(1),N(2),N(3));
fclose(fileID);
end
end
%% Evaluation of multiple looks
if size(sigma,5) > 1
sigma = mean(sigma,5);
end
%% Similarity estimation
if flags.do_isd && flags.do_sigmoid
% duration-dependence of gamma (degree of selectivity)
if length(kv.stim)/kv.fs < 5e-3 % halfen if shorter than 5ms
kv.gamma = kv.gamma*kv.gammashortfact;
end
% duration-dependence of sensitivity
if length(kv.stim)/kv.fs < 5e-3 % halfen if shorter than 5ms
kv.S = kv.S*kv.Sshortfact;
end
if not(flags.do_gammatone)
sigma = 10*sigma;
end
si = baumgartner2014_similarityestimation(sigma,'S',kv.S,'gamma',kv.gamma);
else
amt_disp('Similarity estimation different to baumgartner2014','progress')
if flags.do_zilany2014 && not(flags.do_sigmoid || flags.do_dcn)
sigma = sigma/10;
end
si=zeros(size(sigma)); % init
for ch = 1:size(mreptar,3)
for it = 1:size(mreptar,2)
if flags.do_isd
if flags.do_sigmoid
si(:,it,ch) = 1+eps - (1+exp(-kv.gamma*(sigma(:,it,ch)-10*kv.S))).^-1;
elseif flags.do_exp
si(:,it,ch) = real(exp(-sigma(:,it,ch)./kv.S));
elseif flags.do_Gauss
si(:,it,ch) = real(exp(-(sigma(:,it,ch)./kv.S).^2));
else
si(:,it,ch) = interp1([0,kv.SimDL,kv.S,1e10],[1,1,0,0],sigma(:,it,ch),'cubic');
end
elseif flags.do_corr
if flags.do_exp
si(:,it,ch) = real(exp( (sigma(:,it,ch) - 1)./kv.S ));
elseif flags.do_Gauss
si(:,it,ch) = real(exp(-((sigma(:,it,ch) - 1)./kv.S).^2));
else % power law relationship
si(:,it,ch) = real(sigma(:,it,ch).^kv.S);
end
end
end
end
end
%% Binaural weighting
si = baumgartner2014_binauralweighting(si,'lat',kv.lat,'bwcoef',kv.bwcoef);
%% Interpolation, prior, sensorimotor mapping
if kv.prior==0
[si,rang] = baumgartner2014_sensorimotormapping(si,...
'rangsamp',kv.rangsamp,'polsamp',kv.polsamp,'lat',kv.lat,'mrsmsp',kv.mrsmsp,...
flags.regularization,flags.motoricresponsescatter);
else
if flags.do_regular
rang0 = ceil(min(kv.polsamp)*0.2)*5; % ceil to 5 deg
rang = rang0:kv.rangsamp:max(kv.polsamp);
siint = zeros(length(rang),size(si,2));
for tt = 1:size(si,2)
siint(:,tt) = interp1(kv.polsamp,si(:,tt),rang,'spline');
end
si = siint;
si(si<0) = 0; % SIs must be positive (necessary due to spline interp)
else
rang = kv.polsamp;
end
% Individual prior distribution
if min(kv.priordist.x) > -90
kv.priordist.x = [-90;kv.priordist.x(:)];
kv.priordist.y = [1;kv.priordist.y(:)];
end
if max(kv.priordist.x) < 270
kv.priordist.x = [kv.priordist.x(:);270];
kv.priordist.y = [kv.priordist.y(:);1];
end
priordist = interp1(kv.priordist.x,kv.priordist.y,rang,'linear') .^ kv.prior;
si = si.*repmat(priordist(:),1,size(si,2));
% Sensorimotor mapping
if flags.do_mrs && flags.do_regular && kv.mrsmsp > 0
angbelow = -90:5:min(rang)-5;
angabove = max(rang)+5:5:265;
rang = [angbelow,rang,angabove];
si = [zeros(length(angbelow),size(si,2)) ; si ; zeros(length(angabove),size(si,2))];
mrs = kv.mrsmsp/cos(deg2rad(kv.lat)); % direction dependent scatter (derivation: const. length rel. to the circumferences of circles considered as cross sections of a unit sphere)
x = 0:2*pi/72:2*pi-2*pi/72;
kappa = 1/deg2rad(mrs)^2; % concentration parameter (~1/sigma^2 of normpdf)
mrspdf = exp(kappa*cos(x)) / (2*pi*besseli(0,kappa)); % von Mises PDF
for tt = 1:size(si,2)
si(:,tt) = pconv(si(:,tt),mrspdf(:));
end
end
end
%% Normalization to PMV
p = si ./ repmat(sum(si)+eps,size(si,1),1);
%% Performance measures
if not(isempty(flags.errorflag)) % Simulate virtual experiments
m = baumgartner2014_virtualexp(p,tang,rang,'targetset',kv.exptang);
err = localizationerror(m,flags.errorflag);
elseif not(isempty(flags.ppp)) % Calculate directly via probabilities
if flags.do_QE_PE_EB
[err.qe,err.pe,err.pb] = baumgartner2014_pmv2ppp(p,tang,rang,'exptang',kv.exptang);
else
err = baumgartner2014_pmv2ppp(p,tang,rang,flags.ppp,'exptang',kv.exptang);
end
end
%% Output
if isempty([flags.errorflag,flags.ppp])
varargout{1} = p;
if nargout >= 2
varargout{2} = rang;
if nargout >= 3
try
varargout{3} = tang;
catch
amt_disp('SOFA Object of target DTFs is required to output target angles.')
end
end
end
else
varargout{1} = err;
if nargout > 1
varargout{2} = struct('p',p,'rang',rang,'tang',tang);
if nargout > 2
if not(exist('m','var'))
m = baumgartner2014_virtualexp(p,tang,rang);
end
varargout{3} = m;
end
end
end
end
% function t4 = psge(an,fc,c2)
% %DCN Phenomenological model of dorsal cochlear nucleus (DCN)
% % Usage: out = dcn(in)
% %
% % Input parameters:
% % an : spectral profile in dB
% %
% % Output parameters:
% % t4 : activity of type IV unit
%
% %% Parameter Settings
% % c2 = 1; % inhibitory coupling between type II and type IV neurons
% c4 = 1; % coupling between an and type IV neuron
% dilatation = 1; % of tonotopical 1-ERB-spacing between type IV and II neurons
%
% erb = audfiltbw(fc);
%
% %% Calculations
% Nb = size(an,1); % # auditory bands
% dt4t2 = round(mean(erb(2:end)./diff(fc))*dilatation); % tonotopical distance between type IV and II neurons
% t4 = zeros(Nb-dt4t2,size(an,2),size(an,3)); % type IV output
% for b = 1:Nb-dt4t2
% t4(b,:,:) = c4 * an(b+dt4t2,:,:) - c2 * an(b,:,:);
% end
%
% t4 = (t4 + c2*abs(t4))/2; %disp('only rising edges')
% % t4(t4<0) = nan;
% end
function P = dcn(an,fc)
%DCN Phenomenological model of dorsal cochlear nucleus (DCN)
% Usage: P = dcn(an,fc)
%
% Input parameters:
% an : spectral profile in dB
%
% Output parameters:
% P : activity of principal cell
%% Parameter Settings (Table 2, Lomakin & Davis, 2008)
% offsets in octaves
c.WtoI2 = .3;
c.WtoP = .2;
c.I2toP = -.1;
% bandwidth in octaves
bw.ANtoW = 2.5; % effectively .83 due to Gaussian distribution
bw.ANtoI2 = .4;
bw.ANtoP = .4;
bw.WtoI2 = 2.2; % from Fig. 7
bw.WtoP = 2.2; % from Fig. 7
bw.I2toP = .2;
% # projections times strength
Ns.ANtoW = 140*.05;
Ns.ANtoI2 = 48*.55;
Ns.ANtoP = 48*.25;
Ns.WtoI2 = 15*1.4;
Ns.WtoP = 15*.6; % from page 514
Ns.I2toP = 21*2.25;
% non-specific afferents (NSA) leading to spontaneous activity
nsa = 3000; % spikes/s
%% Parameter Settings (Table 1, Reiss & Young, 2005)
% % offsets in octaves
% c.WtoI2 = .3;
% c.WtoP = .05;
% c.I2toP = -.1;
% % bandwidth in octaves
% bw.ANtoI2 = .2;
% bw.ANtoW = 2.0;
% bw.ANtoP = .24;
% bw.WtoI2 = 0.1;%0.05;
% bw.WtoP = 0.1;
% bw.I2toP = .2;
% % # projections times strength
% Ns.ANtoI2 = 23.1;
% Ns.ANtoW = 10.8;
% Ns.ANtoP = 2.75;
% Ns.WtoI2 = 7;
% Ns.WtoP = 0;
% Ns.I2toP = 47.25;
% % non-specific afferents (NSA) leading to spontaneous activity
% nsa = 0; % spikes/s
%% Calculations
Nf = length(fc);
% df = mean(diff(fc));
W = nan(size(an));
for ii = 1:Nf
nANtoW = fc >= fc(ii)*2^(-bw.ANtoW/2) & fc <= fc(ii)*2^(bw.ANtoW/2);
win = gausswin(sum(nANtoW)); win = win/sum(win);
W(ii,:) = Ns.ANtoW * win' * an(nANtoW,:);
% W(ii,:) = Ns.ANtoW*mean(an(nANtoW,:));
end
% W = max(W,0);
I2 = nan(size(an));
for ii = 1:Nf
nANtoI2 = fc >= fc(ii)*2^(-bw.ANtoI2/2) & fc <= fc(ii)*2^(bw.ANtoI2/2);
win = gausswin(sum(nANtoI2)); win = win/sum(win);
ANtoI2(ii,:) = Ns.ANtoI2 * win' * an(nANtoI2,:);
nWtoI2 = fc >= fc(ii)*2^(c.WtoI2-bw.WtoI2/2) & fc <= fc(ii)*2^(c.WtoI2+bw.WtoI2/2);
if sum(nWtoI2) == 0; nWtoI2(end) = 1; end % for high fc
win = gausswin(sum(nWtoI2)); win = win/sum(win);
WtoI2(ii,:) = Ns.WtoI2 * win' * W(nWtoI2,:);
I2(ii,:) = ANtoI2(ii,:) - WtoI2(ii,:);
% I2(ii,:) = Ns.ANtoI2*mean(an(nANtoI2,:)) - Ns.WtoI2*mean(an(nWtoI2,:));
end
% I2 = max(I2,0);
ANtoP = nan(size(an));
WtoP = ANtoP;
I2toP = ANtoP;
P = nan(size(an));
for ii = 1:Nf
nANtoP = fc >= fc(ii)*2^(-bw.ANtoP/2) & fc <= fc(ii)*2^(bw.ANtoP/2);
win = gausswin(sum(nANtoP)); win = win/sum(win);
ANtoP(ii,:) = Ns.ANtoP * win' * an(nANtoP,:);
nWtoP = fc >= fc(ii)*2^(c.WtoP-bw.WtoP/2) & fc <= fc(ii)*2^(c.WtoP+bw.WtoP/2);
win = gausswin(sum(nWtoP)); win = win/sum(win);
WtoP(ii,:) = Ns.WtoP * win' * W(nWtoP,:);
nI2toP = fc >= fc(ii)*2^(c.I2toP-bw.I2toP/2) & fc <= fc(ii)*2^(c.I2toP+bw.I2toP/2);
win = gausswin(sum(nI2toP)); win = win/sum(win);
I2toP(ii,:) = Ns.I2toP * win' * I2(nI2toP,:);
P(ii,:) = nsa + ANtoP(ii,:) - WtoP(ii,:) - I2toP(ii,:);
% P(ii,:) = nsa + Ns.ANtoP*mean(an(nANtoP,:)) - Ns.WtoP*mean(W(nWtoP,:)) - Ns.I2toP*mean(I2(nI2toP,:));
end
% P = P/max(P(:));
% P(P<0.4) = nan;
% P = P(1:90,:);
% P = max(P,0);
end
function v = nanmean (X, varargin)
% NANMEAN
% v = nanmean (X)
n = sum (~isnan(X), varargin{:});
n(n == 0) = NaN;
X(isnan(X)) = 0;
v = sum (X, varargin{:}) ./ n;
end