Skip to content

Commit

Permalink
bugfixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthias Treder committed Sep 7, 2012
1 parent 3c8bca5 commit 6cf073e
Show file tree
Hide file tree
Showing 18 changed files with 445 additions and 77 deletions.
10 changes: 6 additions & 4 deletions processing/proc_appendSamples.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
%Returns:
% fv - updated feature vector
%
misc_checkType(fv1,'STRUCT(x className)');

fv1 = misc_history(fv1);


Expand All @@ -20,7 +22,7 @@
error('dimension mismatch');
end

if isfield(fv1, 'className') & isfield(fv2, 'className'),
if isfield(fv1, 'className') && isfield(fv2, 'className'),
if ~isequal(fv1.className, fv2.className),
error('class mismatch');
end
Expand All @@ -30,14 +32,14 @@
end


fv= copy_struct(fv1, 'not', 'x','jit','bidx');
fv= rmfield(fv1,intersect(fieldnames(fv1),{ 'x','jit','bidx'}) );
fv.x= cat(nd, fv1.x, fv2.x);
fv.y= cat(2, fv1.y, fv2.y);

if isfield(fv1, 'jit') & isfield(fv2, 'jit'),
if isfield(fv1, 'jit') && isfield(fv2, 'jit'),
fv.jit= cat(2, fv1.jit, fv2.jit);
end

if isfield(fv1, 'bidx') & isfield(fv2, 'bidx'),
if isfield(fv1, 'bidx') && isfield(fv2, 'bidx'),
fv.bidx= cat(2, fv1.bidx, fv2.bidx);
end
2 changes: 1 addition & 1 deletion processing/proc_fisherScore.m
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
fscore= ((me(:,1)-me(:,2)).^2)./(va(:,1)+va(:,2)+eps);
fscore= reshape(fscore, [sz(1:end-1) 1]);

fv_fscore= copy_struct(fv, 'not', 'x','y','className');
fv_fscore= rmfield(fv, intersect(fieldnames(fv),{'x','y','className'}) );
fv_fscore.x= fscore;
if isfield(fv, 'className'),
fv_fscore.className= {sprintf('Fs( %s , %s )', fv.className{1:2})};
Expand Down
192 changes: 192 additions & 0 deletions processing/proc_grandAverage.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
function ga= proc_grandAverage(varargin)
% PROC_GRANDAVERAGE - calculates the grand average ERPs or ERD/ERS from given set of
% data.
%
%Usage:
%ga= proc_grandAverage(erps)
%ga= proc_grandAverage(erps, <OPT>)
%ga= proc_grandAverage(erp1, <erp2, ..., erpN>, <Prop1>, <Val1>, ...)
%
% IN erps - cell array of erp structures
% erpn - erp structure
%
% <OPT> - struct or property/value list of optional fields/properties:
% Average - If 'weighted', each ERP is weighted for the number of
% epochs (giving less weight to ERPs made from a small number
% of epochs). Default 'unweighted'
% MustBeEqual - fields in the erp structs that must be equal across
% different structs, otherwise an error is issued
% (default {'fs','y','className'})
% ShouldBeEqual - fields in the erp structs that should be equal across
% different structs, gives a warning otherwise
% (default {'yUnit'})
%Output:
% ga: Grand average
%

props = { 'Average' 'unweighted' '!CHAR(weighted unweighted)';
'MustBeEqual' {'fs','y','className'} 'CHAR|CELL{CHAR}';
'ShouldBeEqual' {'yUnit'} 'CHAR|CELL{CHAR}';
};

if nargin==0,
ga=props; return
end

%% Process input arguments
if iscell(varargin{1}),
erps= varargin{1};
opt= opt_proplistToStruct(varargin{2:end});
else
iserp= ~cellfun(@ischar,varargin);
nerps= find(iserp,1,'last');
erps= varargin(1:nerps);
opt= opt_proplistToStruct(varargin{nerps+1:end});
end


[opt, isdefault]= opt_setDefaults(opt, props);
opt_checkProplist(opt, props);

misc_checkType(erps,'CELL{STRUCT}');

%% Get common electrode set
clab= erps{1}.clab;
for ii= 2:length(erps),
clab= intersect(clab, erps{ii}.clab);
end
if isempty(clab),
error('intersection of channels is empty');
end

%% Define ga data field
datadim = unique(cellfun(@util_getDataDimension,erps));
if numel(datadim) > 1
error('Datasets have different dimensionalities');
end

ga= rmfield(erps{1},intersect(fieldnames(erps{1}),'x'));
must_be_equal= intersect(opt.MustBeEqual, fieldnames(ga));
should_be_equal= intersect(opt.ShouldBeEqual, fieldnames(ga));

if datadim==1
T= size(erps{1}.x, 1);
E= size(erps{1}.x, 3);
ci= util_chanind(erps{1}, clab);
X= zeros([T length(ci) E length(erps)]);
else
ci= util_chanind(erps{1}, clab);
% Timefrequency data
if ndims(erps{1}.x)==3 % no classes, erps are averages over single class
F= size(erps{1}.x, 1);
T= size(erps{1}.x, 2);
X= zeros([F T length(ci) length(erps)]);
elseif ndims(erps{1}.x)==4
F= size(erps{1}.x, 1);
T= size(erps{1}.x, 2);
E= size(erps{1}.x, 4);
X= zeros([F T length(ci) E length(erps)]);
end
end

%% Store all erp data in X
for ii= 1:length(erps),
for jj= 1:length(must_be_equal),
fld= must_be_equal{jj};
if ~isequal(getfield(ga,fld), getfield(erps{ii},fld)),
error('inconsistency in field %s.', fld);
end
end
for jj= 1:length(should_be_equal),
fld= should_be_equal{jj};
if ~isequal(getfield(ga,fld), getfield(erps{ii},fld)),
warning('inconsistency in field %s.', fld);
end
end
ci= util_chanind(erps{ii}, clab);
if isfield(ga, 'V')
iV(:,:,:,ii)= 1./erps{ii}.V;
end

if datadim==1
X(:,:,:,ii)= erps{ii}.x(:,ci,:);
else
if ndims(erps{1}.x)==3
X(:,:,:,ii)= erps{ii}.x(:,:,ci);
elseif ndims(erps{1}.x)==4
X(:,:,:,:,ii)= erps{ii}.x(:,:,ci,:);
end
end
end

%% Perform averaging
if isfield(ga, 'yUnit') && strcmp(ga.yUnit, 'dB'),
X= 10.^(X/10);
end
if isfield(ga, 'yUnit') && strcmp(ga.yUnit, 'r'),
if strcmp(opt.Average, 'weighted'),
% does it make sense to use weighting here?
warning('weighted averaging not implemented for this case - ask Stefan');
end
ga.V = 1./sum(iV, 4);
z = sum(atanh(X).*iV, 4).*ga.V;
ga.x= tanh(z);
ga.p = reshape(2*normal_cdf(-abs(z(:)), zeros(size(z(:))), sqrt(ga.V(:))), size(z));
else
if strcmp(opt.Average, 'weighted'),
if datadim==1
ga.x= zeros([T length(ci) E]);
for cc= 1:size(X, 3), %% for each class
nTotalTrials= 0;
for vp= 1:size(X, 4), %% average across subjects
% TODO: sort out NaNs
ga.x(:,:,cc)= ga.x(:,:,cc) + erps{vp}.N(cc)*X(:,:,cc,vp);
nTotalTrials= nTotalTrials + erps{vp}.N(cc);
end
ga.x(:,:,cc)= ga.x(:,:,cc)/nTotalTrials;
end
else
% Timefrequency data
if ndims(erps{1}.x)==3 % only one class
ga.x= zeros([F T length(ci)]);
nTotalTrials= 0;
for vp= 1:size(X, 4), %% average across subjects
% TODO: sort out NaNs
ga.x = ga.x + erps{vp}.N*X(:,:,:,vp);
nTotalTrials= nTotalTrials + erps{vp}.N;
end
ga.x = ga.x/nTotalTrials;

elseif ndims(erps{1}.x)==4
ga.x= zeros([F T length(ci) E]);
for cc= 1:size(X, 4), %% for each class
nTotalTrials= 0;
for vp= 1:size(X, 5), %% average across subjects
% TODO: sort out NaNs
ga.x(:,:,:,cc)= ga.x(:,:,:,cc) + erps{vp}.N(cc)*X(:,:,:,cc,vp);
nTotalTrials= nTotalTrials + erps{vp}.N(cc);
end
ga.x(:,:,:,cc)= ga.x(:,:,:,cc)/nTotalTrials;
end
end

end
else
% Unweighted
if datadim==1 || ndims(erps{1}.x)==3
ga.x= nanmean(X, 4);
else
ga.x= nanmean(X, 5);
end
end
end
if isfield(ga, 'yUnit') && strcmp(ga.yUnit, 'dB'),
ga.x= 10*log10(ga.x);
end

ga.clab= clab;
%% TODO should allow for weighting accoring to field N
%% (but this has to happen classwise)

ga.title= 'grand average';
ga.N= length(erps);
31 changes: 15 additions & 16 deletions processing/proc_linearDerivation.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
% appendix - in case of input-output channel matching
% this string is appended to channel labels, default ''
% OPT - struct or property/value list of properties:
% .clab - cell array of channel labels to be used for new channels,
% .CLab - cell array of channel labels to be used for new channels,
% or 'generic' which uses {'ch1', 'ch2', ...}
% or 'copy' which copies the channel labels from input struct.
% .appendix - (as above) tries to find (naive) channel matching
% and uses as channel labels: old label plus opt.appendix.
% .Appendix - (as above) tries to find (naive) channel matching
% and uses as channel labels: old label plus opt.Appendix.
%
%Returns:
% dat - updated data structure
Expand All @@ -26,9 +26,9 @@

% Benjamin Blankertz
% 07-2012 Johannes Hoehne - Updated documentation and parameter naming
props= {'clab' [] 'CHAR';
'prependix' '' 'CHAR';
'appendix' '' 'CHAR'
props= {'CLab' [] 'CHAR';
'Prependix' '' 'CHAR';
'Appendix' '' 'CHAR'
};

if nargin==0,
Expand All @@ -48,7 +48,6 @@

[opt, isdefault]= opt_setDefaults(opt, props);

%out= copy_struct(dat, 'not', 'x','clab');
out= dat;

nNewChans= size(A,2);
Expand All @@ -61,21 +60,21 @@
out.x= permute(reshape(out.x, [sz(1) sz(3) nNewChans]), [1 3 2]);
end

if ~isdefault.clab,
if isequal(opt.clab, 'generic'),
if ~isdefault.CLab,
if isequal(opt.CLab, 'generic'),
out.clab= cellstr([repmat('ch',nNewChans,1) int2str((1:nNewChans)')])';
elseif isequal(opt.clab, 'copy'),
elseif isequal(opt.CLab, 'copy'),
out.clab= dat.clab;
else
out.clab= opt.clab;
out.clab= opt.CLab;
end
elseif ~isdefault.prependix,
elseif ~isdefault.Prependix,
% the following results, e.g., in 'csp 1', but the space is impractical
% out.clab= cellstr([repmat(opt.prependix,nNewChans,1) ...
% out.clab= cellstr([repmat(opt.Prependix,nNewChans,1) ...
% int2str((1:nNewChans)')])';
out.clab= cell(1,nNewChans);
for ic= 1:nNewChans,
out.clab{ic}= [opt.prependix int2str(ic)];
out.clab{ic}= [opt.Prependix int2str(ic)];
end
else
no= NaN*ones(1, nNewChans);
Expand All @@ -89,11 +88,11 @@
out.clab= cell(1,nNewChans);
if ~any(isnan(no)),
for ic= 1:nNewChans,
out.clab{ic}= [dat.clab{no(ic)} opt.appendix];
out.clab{ic}= [dat.clab{no(ic)} opt.Appendix];
end
else
for ic= 1:nNewChans,
out.clab{ic}= [opt.prependix int2str(ic)];
out.clab{ic}= [opt.Prependix int2str(ic)];
end
end
end
Expand Down
Loading

0 comments on commit 6cf073e

Please sign in to comment.