a b/code/preprocessing/EEG/fastica/icaplot.m
1
function icaplot(mode, varargin);
2
%ICAPLOT - plot signals in various ways
3
%
4
% ICAPLOT is mainly for plottinf and comparing the mixed signals and
5
% separated ica-signals.
6
%
7
% ICAPLOT has many different modes. The first parameter of the function
8
% defines the mode. Other parameters and their order depends on the
9
% mode. The explanation for the more common parameters is in the end.
10
%
11
% Classic
12
%     icaplot('classic', s1, n1, range, xrange, titlestr)
13
%
14
%     Plots the signals in the same manner as the FASTICA and FASTICAG
15
%     programs do. All the signals are plotted in their own axis.
16
%
17
% Complot
18
%     icaplot('complot', s1, n1, range, xrange, titlestr)
19
%
20
%     The signals are plotted on the same axis. This is good for
21
%     visualization of the shape of the signals. The scale of the signals 
22
%     has been altered so that they all fit nicely.
23
%
24
% Histogram
25
%     icaplot('histogram', s1, n1, range, bins, style)
26
%     
27
%     The histogram of the signals is plotted. The number of bins can be
28
%     specified with 'bins'-parameter. The style for the histograms can
29
%     be either 'bar' (default) of 'line'.
30
%
31
% Scatter
32
%     icaplot('scatter', s1, n1, s2, n2, range, titlestr, s1label,
33
%     s2label, markerstr)
34
%
35
%     A scatterplot is plotted so that the signal 1 is the 'X'-variable
36
%     and the signal 2 is the 'Y'-variable. The 'markerstr' can be used
37
%     to specify the maker used in the plot. The format for 'markerstr'
38
%     is the same as for Matlab's PLOT. 
39
%
40
% Compare
41
%     icaplot('compare', s1, n1, s2, n2, range, xrange, titlestr,
42
%     s1label, s2label)
43
%
44
%     This for for comparing two signals. The main used in this context
45
%     would probably be to see how well the separated ICA-signals explain 
46
%     the observed mixed signals. The s2 signals are first scaled with
47
%     REGRESS function.
48
%
49
% Compare - Sum
50
%     icaplot('sum', s1, n1, s2, n2, range, xrange, titlestr, s1label,
51
%     s2label)
52
%
53
%     The same as Compare, but this time the signals in s2 (specified by
54
%     n2) are summed together.
55
%
56
% Compare - Sumerror
57
%     icaplot('sumerror', s1, n1, s2, n2, range, xrange, titlestr,
58
%     s1label, s2label)
59
%     
60
%     The same as Compare - Sum, but also the 'error' between the signal
61
%     1 and the summed IC's is plotted.
62
%
63
%
64
% More common parameters
65
%     The signals to be plotted are in matrices s1 and s2. The n1 and n2
66
%     are used to tell the index of the signal or signals to be plotted
67
%     from s1 or s2. If n1 or n2 has a value of 0, then all the signals
68
%     from corresponding matrix will be plotted. The values for n1 and n2 
69
%     can also be vectors (like: [1 3 4]) In some casee if there are more
70
%     than 1 signal to be plotted from s1 or s2 then the plot will
71
%     contain as many subplots as are needed. 
72
%
73
%     The range of the signals to be plotted can be limited with
74
%     'range'-parameter. It's value is a vector ( 10000:15000 ). If range 
75
%     is 0, then the whole range will be plotted.
76
%
77
%     The 'xrange' is used to specify only the labels used on the
78
%     x-axis. The value of 'xrange' is a vector containing the x-values
79
%     for the plots or [start end] for begin and end of the range
80
%     ( 10000:15000 or [10 15] ). If xrange is 0, then value of range
81
%     will be used for x-labels.
82
%
83
%     You can give a title for the plot with 'titlestr'. Also the
84
%     's1label' and 's2label' are used to give more meaningfull label for 
85
%     the signals.
86
%
87
%     Lastly, you can omit some of the arguments from the and. You will
88
%     have to give values for the signal matrices (s1, s2) and the
89
%     indexes (n1, n2)
90
91
% @(#)$Id$
92
93
switch mode
94
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95
  % 'dispsig' is to replace the old DISPSIG
96
  % '' & 'classic' are just another names - '' quite short one :-)
97
 case {'', 'classic', 'dispsig'} 
98
  % icaplot(mode, s1, n1, range, xrange, titlestr)
99
  if length(varargin) < 1, error('Not enough arguments.'); end
100
  if length(varargin) < 5, titlestr = '';else titlestr = varargin{5}; end
101
  if length(varargin) < 4, xrange = 0;else xrange = varargin{4}; end
102
  if length(varargin) < 3, range = 0;else range = varargin{3}; end
103
  if length(varargin) < 2, n1 = 0;else n1 = varargin{2}; end
104
  s1 = varargin{1};
105
  range=chkrange(range, s1);
106
  xrange=chkxrange(xrange, range);
107
  n1=chkn(n1, s1);
108
109
  clf;
110
  
111
  numSignals = size(n1, 2);
112
  for i = 1:numSignals,
113
    subplot(numSignals, 1, i);
114
    plot(xrange, s1(n1(i), range));
115
  end
116
  subplot(numSignals,1, 1);
117
  if (~isempty(titlestr))
118
    title(titlestr);
119
  end
120
  
121
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122
 case 'complot'
123
  % icaplot(mode, s1, n1, range, xrange, titlestr)
124
  if length(varargin) < 1, error('Not enough arguments.'); end
125
  if length(varargin) < 5, titlestr = '';else titlestr = varargin{5}; end
126
  if length(varargin) < 4, xrange = 0;else xrange = varargin{4}; end
127
  if length(varargin) < 3, range = 0;else range = varargin{3}; end
128
  if length(varargin) < 2, n1 = 0;else n1 = varargin{2}; end
129
  s1 = remmean(varargin{1});
130
  range=chkrange(range, s1);
131
  xrange=chkxrange(xrange, range);
132
  n1=chkn(n1, s1);
133
  
134
  for i = 1:size(n1, 2)
135
    S1(i, :) = s1(n1(i), range);
136
  end
137
  
138
  alpha = mean(max(S1')-min(S1'));
139
  for i = 1:size(n1,2)
140
    S2(i,:) = S1(i,:) - alpha*(i-1)*ones(size(S1(1,:)));
141
  end
142
  
143
  plot(xrange, S2');
144
  axis([min(xrange) max(xrange) min(min(S2)) max(max(S2)) ]);
145
  
146
  set(gca,'YTick',(-size(S1,1)+1)*alpha:alpha:0);
147
  set(gca,'YTicklabel',fliplr(n1));
148
  
149
  if (~isempty(titlestr))
150
    title(titlestr);
151
  end
152
153
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154
 case 'histogram'
155
  % icaplot(mode, s1, n1, range, bins, style)
156
  if length(varargin) < 1, error('Not enough arguments.'); end
157
  if length(varargin) < 5, style = 'bar';else style = varargin{5}; end
158
  if length(varargin) < 4, bins = 10;else bins = varargin{4}; end
159
  if length(varargin) < 3, range = 0;else range = varargin{3}; end
160
  if length(varargin) < 2, n1 = 0;else n1 = varargin{2}; end
161
  s1 = varargin{1};
162
  range = chkrange(range, s1);
163
  n1 = chkn(n1, s1);
164
  
165
  numSignals = size(n1, 2);
166
  rows = floor(sqrt(numSignals));
167
  columns = ceil(sqrt(numSignals));
168
  while (rows * columns < numSignals)
169
    columns = columns + 1;
170
  end
171
  
172
  switch style
173
   case {'', 'bar'}
174
    for i = 1:numSignals,
175
      subplot(rows, columns, i);
176
      hist(s1(n1(i), range), bins);
177
      title(int2str(n1(i)));
178
      drawnow;
179
    end
180
    
181
   case 'line'
182
    for i = 1:numSignals,
183
      subplot(rows, columns, i);
184
      [Y, X]=hist(s1(n1(i), range), bins);
185
      plot(X, Y);
186
      title(int2str(n1(i)));
187
      drawnow;
188
    end
189
   otherwise
190
    fprintf('Unknown style.\n')
191
  end
192
193
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194
 case 'scatter'
195
  % icaplot(mode, s1, n1, s2, n2, range, titlestr, xlabelstr, ylabelstr, markerstr)
196
  if length(varargin) < 4, error('Not enough arguments.'); end
197
  if length(varargin) < 9, markerstr = '.';else markerstr = varargin{9}; end
198
  if length(varargin) < 8, ylabelstr = 'Signal 2';else ylabelstr = varargin{8}; end
199
  if length(varargin) < 7, xlabelstr = 'Signal 1';else xlabelstr = varargin{7}; end
200
  if length(varargin) < 6, titlestr = '';else titlestr = varargin{6}; end
201
  if length(varargin) < 5, range = 0;else range = varargin{5}; end
202
  n2 = varargin{4};
203
  s2 = varargin{3};
204
  n1 = varargin{2};
205
  s1 = varargin{1};
206
  range = chkrange(range, s1);
207
  n1 = chkn(n1, s1);
208
  n2 = chkn(n2, s2);
209
  
210
  rows = size(n1, 2);
211
  columns = size(n2, 2);
212
  for r = 1:rows
213
    for c = 1:columns
214
      subplot(rows, columns, (r-1)*columns + c);
215
      plot(s1(n1(r), range),s2(n2(c), range),markerstr);
216
      if (~isempty(titlestr))
217
    title(titlestr);
218
      end
219
      if (rows*columns == 1)
220
    xlabel(xlabelstr);
221
    ylabel(ylabelstr);
222
      else 
223
    xlabel([xlabelstr ' (' int2str(n1(r)) ')']);
224
    ylabel([ylabelstr ' (' int2str(n2(c)) ')']);
225
      end
226
      drawnow;
227
    end
228
  end
229
  
230
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231
 case {'compare', 'sum', 'sumerror'}
232
  % icaplot(mode, s1, n1, s2, n2, range, xrange, titlestr, s1label, s2label)
233
  if length(varargin) < 4, error('Not enough arguments.'); end
234
  if length(varargin) < 9, s2label = 'IC';else s2label = varargin{9}; end
235
  if length(varargin) < 8, s1label = 'Mix';else s1label = varargin{8}; end
236
  if length(varargin) < 7, titlestr = '';else titlestr = varargin{7}; end
237
  if length(varargin) < 6, xrange = 0;else xrange = varargin{6}; end
238
  if length(varargin) < 5, range = 0;else range = varargin{5}; end
239
  s1 = varargin{1};
240
  n1 = varargin{2};
241
  s2 = varargin{3};
242
  n2 = varargin{4};
243
  range = chkrange(range, s1);
244
  xrange = chkxrange(xrange, range);
245
  n1 = chkn(n1, s1);
246
  n2 = chkn(n2, s2);
247
248
  numSignals = size(n1, 2);
249
  if (numSignals > 1)
250
    externalLegend = 1;
251
  else
252
    externalLegend = 0;
253
  end
254
  
255
  rows = floor(sqrt(numSignals+externalLegend));
256
  columns = ceil(sqrt(numSignals+externalLegend));
257
  while (rows * columns < (numSignals+externalLegend))
258
    columns = columns + 1;
259
  end
260
  
261
  clf;
262
  
263
  for j = 1:numSignals
264
    subplot(rows, columns, j);
265
    switch mode
266
     case 'compare'
267
      plotcompare(s1, n1(j), s2,n2, range, xrange);
268
      [legendtext,legendstyle]=legendcompare(n1(j),n2,s1label,s2label,externalLegend);
269
     case 'sum'
270
      plotsum(s1, n1(j), s2,n2, range, xrange);
271
      [legendtext,legendstyle]=legendsum(n1(j),n2,s1label,s2label,externalLegend);
272
     case 'sumerror'
273
      plotsumerror(s1, n1(j), s2,n2, range, xrange);
274
      [legendtext,legendstyle]=legendsumerror(n1(j),n2,s1label,s2label,externalLegend);
275
    end
276
    
277
    if externalLegend
278
      title([titlestr ' (' s1label  ' ' int2str(n1(j)) ')']);
279
    else
280
      legend(char(legendtext));
281
      if (~isempty(titlestr))
282
    title(titlestr);
283
      end
284
    end
285
  end
286
  
287
  if (externalLegend)
288
    subplot(rows, columns, numSignals+1);
289
    legendsize = size(legendtext, 2);
290
    hold on;
291
    for i=1:legendsize
292
      plot([0 1],[legendsize-i legendsize-i], char(legendstyle(i)));
293
      text(1.5, legendsize-i, char(legendtext(i)));
294
    end
295
    hold off;
296
    axis([0 6 -1 legendsize]);
297
    axis off;
298
  end
299
  
300
301
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302
end
303
304
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305
function plotcompare(s1, n1, s2, n2, range, xrange);
306
  style=getStyles;
307
  K = regress(s1(n1,:)',s2');
308
  plot(xrange, s1(n1,range), char(style(1)));
309
  hold on
310
  for i=1:size(n2,2)
311
    plotstyle=char(style(i+1));
312
    plot(xrange, K(n2(i))*s2(n2(i),range), plotstyle);
313
  end
314
  hold off
315
316
function [legendText, legendStyle]=legendcompare(n1, n2, s1l, s2l, externalLegend);
317
  style=getStyles;
318
  if (externalLegend)
319
    legendText(1)={[s1l ' (see the titles)']};
320
  else
321
    legendText(1)={[s1l ' ', int2str(n1)]};
322
  end
323
  legendStyle(1)=style(1);
324
  for i=1:size(n2, 2)
325
    legendText(i+1) = {[s2l ' ' int2str(n2(i))]};
326
    legendStyle(i+1) = style(i+1);
327
  end
328
329
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330
function plotsum(s1, n1, s2, n2, range, xrange);
331
  K = diag(regress(s1(n1,:)',s2'));
332
  sigsum = sum(K(:,n2)*s2(n2,:));
333
  plot(xrange, s1(n1, range),'k-', ...
334
       xrange, sigsum(range), 'b-');
335
336
function [legendText, legendStyle]=legendsum(n1, n2, s1l, s2l, externalLegend);
337
  if (externalLegend)
338
    legendText(1)={[s1l ' (see the titles)']};
339
  else
340
    legendText(1)={[s1l ' ', int2str(n1)]};
341
  end
342
  legendText(2)={['Sum of ' s2l ': ', int2str(n2)]};
343
  legendStyle={'k-';'b-'};
344
345
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346
function plotsumerror(s1, n1, s2, n2, range, xrange);
347
  K = diag(regress(s1(n1,:)',s2'));
348
  sigsum = sum(K(:,n2)*s2(n2,:));
349
  plot(xrange, s1(n1, range),'k-', ...
350
       xrange, sigsum(range), 'b-', ...
351
       xrange, s1(n1, range)-sigsum(range), 'r-');
352
353
function [legendText, legendStyle]=legendsumerror(n1, n2, s1l, s2l, externalLegend);
354
  if (externalLegend)
355
    legendText(1)={[s1l ' (see the titles)']};
356
  else
357
    legendText(1)={[s1l ' ', int2str(n1)]};
358
  end
359
  legendText(2)={['Sum of ' s2l ': ', int2str(n2)]};
360
  legendText(3)={'"Error"'};
361
  legendStyle={'k-';'b-';'r-'};
362
363
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
364
function style=getStyles;
365
  color = {'k','r','g','b','m','c','y'};
366
  line = {'-',':','-.','--'};
367
  for i = 0:size(line,2)-1
368
    for j = 1:size(color, 2)
369
      style(j + i*size(color, 2)) = strcat(color(j), line(i+1));
370
    end
371
  end
372
373
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374
function range=chkrange(r, s)
375
  if r == 0
376
    range = 1:size(s, 2);
377
  else
378
    range = r;
379
  end
380
381
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
382
function xrange=chkxrange(xr,r);
383
  if xr == 0
384
    xrange = r;
385
  elseif size(xr, 2) == 2
386
    xrange = xr(1):(xr(2)-xr(1))/(size(r,2)-1):xr(2);
387
  elseif size(xr, 2)~=size(r, 2)
388
    error('Xrange and range have different sizes.');
389
  else
390
    xrange = xr;
391
  end
392
393
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
394
function n=chkn(n,s)
395
  if n == 0
396
    n = 1:size(s, 1);
397
  end