wolffd@0
|
1 function som_trajectory(bmus,varargin)
|
wolffd@0
|
2
|
wolffd@0
|
3 %SOM_TRAJECTORY Launch a "comet" trajectory visualization GUI.
|
wolffd@0
|
4 %
|
wolffd@0
|
5 % som_show(sM,'umat','all')
|
wolffd@0
|
6 % bmus = som_bmus(sM,sD);
|
wolffd@0
|
7 % som_trajectory(bmus)
|
wolffd@0
|
8 % som_trajectory(bmus, 'data1', sD, 'trajsize', [12 6 3 1]')
|
wolffd@0
|
9 % som_trajectory(bmus, 'data1', sD.data(:,[1 2 3]), 'name1', {'fii' 'faa' 'foo'})
|
wolffd@0
|
10 %
|
wolffd@0
|
11 % Input arguments ([]'s are optional):
|
wolffd@0
|
12 % bmus (matrix) size Nx1, vector of BMUS
|
wolffd@0
|
13 % ['argID', (string) Other arguments can be given as 'argID', value
|
wolffd@0
|
14 % value] (varies) pairs. See list below for valid values.
|
wolffd@0
|
15 %
|
wolffd@0
|
16 % NOTE: the GUI only works on a figure which has been made with SOM_SHOW.
|
wolffd@0
|
17 %
|
wolffd@0
|
18 % Here are the valid argument IDs (case insensitive) and associated values:
|
wolffd@0
|
19 % 'color' string 'xor' or ColorSpec, default: 'xor'.
|
wolffd@0
|
20 % (default: according to lattice as in som_cplane)
|
wolffd@0
|
21 % 'TrajSize' vector of size Nx1 to define the length of comet
|
wolffd@0
|
22 % (N) and size of the comet dots in points.
|
wolffd@0
|
23 % default: [16 12 10 8 6 4]'
|
wolffd@0
|
24 % 'Data1' SOM Toolbox data struct or matrix. The size of
|
wolffd@0
|
25 % data matrix (in data struct the field .data) is
|
wolffd@0
|
26 % Nxd, where N must be the same as the amount of
|
wolffd@0
|
27 % BMUS given in the first input argument 'bmus'
|
wolffd@0
|
28 % This data is shown in a new window in d subplots.
|
wolffd@0
|
29 % Default: BMU indices (first input argument)
|
wolffd@0
|
30 % 'Name1' cell array of d strings which contains names
|
wolffd@0
|
31 % for the components in 'Data1'. If 'Data1' is a SOM
|
wolffd@0
|
32 % Toolbox data struct, the existing component names
|
wolffd@0
|
33 % are overdone.
|
wolffd@0
|
34 % 'Figure' scalar that must be a handle to an existing figure
|
wolffd@0
|
35 % which has been made using SOM_SHOW function.
|
wolffd@0
|
36 % Default: current active figure (gcf).
|
wolffd@0
|
37 %
|
wolffd@0
|
38 % The following tools can be found in the 'Tools' -menu.
|
wolffd@0
|
39 %
|
wolffd@0
|
40 % Remove Trajectory: removes trajectory from the map.
|
wolffd@0
|
41 % Dye Nodes : opens GUI for selecting color for the nodes
|
wolffd@0
|
42 % and points selected.
|
wolffd@0
|
43 % Clear Markers : removes markers from map and data figure.
|
wolffd@0
|
44 % Save : saves the current situation as a struct.
|
wolffd@0
|
45 % Load : loads the struct from workspace and draws markers.
|
wolffd@0
|
46 %
|
wolffd@0
|
47 % Mouse operation
|
wolffd@0
|
48 %
|
wolffd@0
|
49 % In data window: Left button is used to drag the operation point ruler
|
wolffd@0
|
50 % if left button is on blank area, it starts
|
wolffd@0
|
51 % In map window : Left button starts a polygon; right button
|
wolffd@0
|
52 % finishes; middle button toggles a unit.
|
wolffd@0
|
53 %
|
wolffd@0
|
54 % SOM_TRAJECTORY is an application for observing trajectory behavior.
|
wolffd@0
|
55 %
|
wolffd@0
|
56 % Using mouse the line in data figure can be dragged and the
|
wolffd@0
|
57 % trajectory moves in the SOM SHOW figure. It is also possible to move
|
wolffd@0
|
58 % trajectory by pressing keys '>' and '<' when mouse pointer is above
|
wolffd@0
|
59 % data figure.
|
wolffd@0
|
60 %
|
wolffd@0
|
61 % Regions can be chosen from the data and the points in that region
|
wolffd@0
|
62 % are mapped to the component planes. Regions can be chosen also in
|
wolffd@0
|
63 % the map. In this situation data points and map nodes are also
|
wolffd@0
|
64 % marked (Left mouse button adds point to the polygon indicating the
|
wolffd@0
|
65 % region and right button finals the polygon). By clicking a node (the
|
wolffd@0
|
66 % middle button) that node is either added or removed from selection.
|
wolffd@0
|
67 %
|
wolffd@0
|
68 % It should be noticed that choosing intervals from data may cause
|
wolffd@0
|
69 % situations that seem to be bugs. If there exisist marks of different
|
wolffd@0
|
70 % color, removing them by clicking the map may left some marks in the
|
wolffd@0
|
71 % data, because more than one point in the data is mapped to the same
|
wolffd@0
|
72 % node in the map and the removing operation depends on the color of
|
wolffd@0
|
73 % the marks. However, all the marks can be removed by using the 'Clear
|
wolffd@0
|
74 % Markers' -operation.
|
wolffd@0
|
75 %
|
wolffd@0
|
76 % FEATURES
|
wolffd@0
|
77 %
|
wolffd@0
|
78 % The first input argument 'bmus' may also be a munits x N matrix
|
wolffd@0
|
79 % In this case each column defines a "fuzzy response". That is,
|
wolffd@0
|
80 % each column defines a hit histogram function). The element
|
wolffd@0
|
81 % bmus(i,t) sets the size of marker on unit i at time t.
|
wolffd@0
|
82 % NOTE: - in this case no regions can be selcted on the map!
|
wolffd@0
|
83 % - only > and < keys can be used to move the operation point
|
wolffd@0
|
84 % line: it can't be dragged
|
wolffd@0
|
85 % - "fuzzy response is always black (hope this will be fixed)
|
wolffd@0
|
86 %
|
wolffd@0
|
87 % It is possible to open a second data window showing different data:
|
wolffd@0
|
88 % use indetifiers 'Data2' (and 'Name2'). The argument syntax is
|
wolffd@0
|
89 % identical to 'Data1' (and 'Name1').
|
wolffd@0
|
90 %
|
wolffd@0
|
91 % See also SOM_SHOW, SOM_SHOW_ADD, SOM_BMUS.
|
wolffd@0
|
92
|
wolffd@0
|
93 % Contributed to SOM Toolbox 2.0, February 11th, 2000 by Johan
|
wolffd@0
|
94 % Himberg and Juha Parhankangas
|
wolffd@0
|
95 % Copyright (c) 2000 by the Johan Himberg and Juha Parhankangas
|
wolffd@0
|
96 % http://www.cis.hut.fi/projects/somtoolbox/
|
wolffd@0
|
97
|
wolffd@0
|
98 % Check arguments
|
wolffd@0
|
99
|
wolffd@0
|
100 error(nargchk(1,Inf,nargin)); % Check no. of input arguments
|
wolffd@0
|
101
|
wolffd@0
|
102 %% Init input argument struct (see subfunction)
|
wolffd@0
|
103 Traj=iniTraj(bmus);
|
wolffd@0
|
104
|
wolffd@0
|
105 % Check tentative BMU input validity
|
wolffd@0
|
106
|
wolffd@0
|
107 if ~vis_valuetype(bmus,{'nxm'}),
|
wolffd@0
|
108 error(['First input should be a vector of BMU indices or' ...
|
wolffd@0
|
109 ' a "response matrix"']);
|
wolffd@0
|
110 end
|
wolffd@0
|
111
|
wolffd@0
|
112 %% Check optional arguments
|
wolffd@0
|
113 for i=1:2:length(varargin)
|
wolffd@0
|
114 identifier=lower(varargin{i});
|
wolffd@0
|
115 value=varargin{i+1};
|
wolffd@0
|
116
|
wolffd@0
|
117 % Trajectory color
|
wolffd@0
|
118 switch identifier
|
wolffd@0
|
119 case 'color'
|
wolffd@0
|
120 if isempty(value)
|
wolffd@0
|
121 value='xor';
|
wolffd@0
|
122 end
|
wolffd@0
|
123 if vis_valuetype(value,{'colorstyle','xor'})
|
wolffd@0
|
124 Traj.color=value;
|
wolffd@0
|
125 else
|
wolffd@0
|
126 error('''Color'' has to be ColorSpec or string ''xor''.');
|
wolffd@0
|
127 end
|
wolffd@0
|
128
|
wolffd@0
|
129 % 1st data
|
wolffd@0
|
130 case 'data1'
|
wolffd@0
|
131 if isempty(value),
|
wolffd@0
|
132 value=[];
|
wolffd@0
|
133 elseif vis_valuetype(value,{'nxm'})
|
wolffd@0
|
134 Traj.primary_data=value;
|
wolffd@0
|
135 elseif isstruct(value) & isfield(value,'type') & ...
|
wolffd@0
|
136 ischar(value.type) & strcmp(value.type,'som_data'),
|
wolffd@0
|
137 Traj.primary_data=value.data;
|
wolffd@0
|
138 if isempty(Traj.primary_names),
|
wolffd@0
|
139 Traj.primary_names=value.comp_names;
|
wolffd@0
|
140 end
|
wolffd@0
|
141 end
|
wolffd@0
|
142
|
wolffd@0
|
143 % 2nd data
|
wolffd@0
|
144 case 'data2'
|
wolffd@0
|
145 if isempty(value),
|
wolffd@0
|
146 value=[];
|
wolffd@0
|
147 elseif vis_valuetype(value,{'nxm'})
|
wolffd@0
|
148 Traj.secondary_data=value;
|
wolffd@0
|
149 elseif isstruct(value) & isfield(value,'type') & ...
|
wolffd@0
|
150 ischar(value.type) & strcmp(value.type,'som_data'),
|
wolffd@0
|
151 Traj.secondary_data=value.data;
|
wolffd@0
|
152 if isempty(Traj.secondary_names),
|
wolffd@0
|
153 Traj.secondary_names=value.comp_names;
|
wolffd@0
|
154 end
|
wolffd@0
|
155 end
|
wolffd@0
|
156
|
wolffd@0
|
157 % Trajectory length & size
|
wolffd@0
|
158 case 'trajsize'
|
wolffd@0
|
159 if isempty(value),
|
wolffd@0
|
160 Traj.size=[16 12 10 8 6 4]';
|
wolffd@0
|
161 end
|
wolffd@0
|
162 if vis_valuetype(value,{'nx1'})
|
wolffd@0
|
163 Traj.size=value
|
wolffd@0
|
164 else
|
wolffd@0
|
165 error('''TrajSize'' has to be a nx1 vector.');
|
wolffd@0
|
166 end
|
wolffd@0
|
167
|
wolffd@0
|
168 % Names for first data variables
|
wolffd@0
|
169 case 'name1'
|
wolffd@0
|
170 if isempty(value),
|
wolffd@0
|
171 Traj.primary_names=[];
|
wolffd@0
|
172 elseif ~vis_valuetype(value,{'cellcolumn_of_char'}),
|
wolffd@0
|
173 error('''Name1'': variable names must be in a cell column array.')
|
wolffd@0
|
174 else
|
wolffd@0
|
175 Traj.primary_names = value;
|
wolffd@0
|
176 end
|
wolffd@0
|
177 % Names for 2nd data variables
|
wolffd@0
|
178 case 'name2'
|
wolffd@0
|
179 if isempty(value),
|
wolffd@0
|
180 Traj.secondary_names=[];
|
wolffd@0
|
181 elseif ~vis_valuetype(value,{'cellcolumn_of_char'}),
|
wolffd@0
|
182 error('''Name2'': variable names must be in a cell column array.')
|
wolffd@0
|
183 else
|
wolffd@0
|
184 Traj.secondary_names = value;
|
wolffd@0
|
185 end
|
wolffd@0
|
186
|
wolffd@0
|
187 % Figure number
|
wolffd@0
|
188 case 'figure'
|
wolffd@0
|
189 if isempty(value)
|
wolffd@0
|
190 Traj.figure='gcf';
|
wolffd@0
|
191 end
|
wolffd@0
|
192 if vis_valuetype(value,{'1x1'})
|
wolffd@0
|
193 Traj.figure=value;
|
wolffd@0
|
194 else
|
wolffd@0
|
195 error('''Figure'' should be number of an existing figure.')
|
wolffd@0
|
196 end
|
wolffd@0
|
197 end
|
wolffd@0
|
198 end
|
wolffd@0
|
199
|
wolffd@0
|
200 %% Get SOM data from figure
|
wolffd@0
|
201 [h,msg,lattice,msize,dim]=vis_som_show_data('all',Traj.figure);
|
wolffd@0
|
202
|
wolffd@0
|
203 %% Not a SOM_SHOW figure?
|
wolffd@0
|
204 if ~isempty(msg);
|
wolffd@0
|
205 error('Figure is invalid: use SOM_SHOW to draw the figure.');
|
wolffd@0
|
206 end
|
wolffd@0
|
207
|
wolffd@0
|
208 % Get map size from figure data
|
wolffd@0
|
209 Traj.lattice=lattice;
|
wolffd@0
|
210 Traj.msize=msize;
|
wolffd@0
|
211 if length(msize)>2,
|
wolffd@0
|
212 error(['This function works only with 2D maps: figure contains' ...
|
wolffd@0
|
213 ' something else.']);
|
wolffd@0
|
214 end
|
wolffd@0
|
215 munits=prod(msize);
|
wolffd@0
|
216
|
wolffd@0
|
217 % Check BMU (or response) and map match
|
wolffd@0
|
218
|
wolffd@0
|
219 if vis_valuetype(bmus,{'nx1'});
|
wolffd@0
|
220 if max(bmus)>prod(msize) | min(bmus) <1
|
wolffd@0
|
221 error('BMU indexes out of range.')
|
wolffd@0
|
222 elseif any(round(bmus)~=bmus)
|
wolffd@0
|
223 error('BMU indexes must be integer.');
|
wolffd@0
|
224 elseif isempty(Traj.primary_data),
|
wolffd@0
|
225 Traj.primary_data=bmus;
|
wolffd@0
|
226 end
|
wolffd@0
|
227 elseif size(bmus,1) ~= munits
|
wolffd@0
|
228 error(['Response matrix column number must match with the number of' ...
|
wolffd@0
|
229 ' map units.']);
|
wolffd@0
|
230 else
|
wolffd@0
|
231 bmus=bmus';
|
wolffd@0
|
232 if isempty(Traj.primary_data),
|
wolffd@0
|
233 Traj.primary_data=[1:size(bmus,1)]';
|
wolffd@0
|
234 Traj.primary_names={'BMU Index'};
|
wolffd@0
|
235 end
|
wolffd@0
|
236 end
|
wolffd@0
|
237
|
wolffd@0
|
238 size1=size(Traj.primary_data);
|
wolffd@0
|
239 size2=size(Traj.secondary_data);
|
wolffd@0
|
240
|
wolffd@0
|
241 % Data2 must not be defined alone
|
wolffd@0
|
242
|
wolffd@0
|
243 if isempty(Traj.primary_data)&~isempty(Traj.secondary_data),
|
wolffd@0
|
244 error('If ''Data2'' is specified ''Data1'' must be specified, too.');
|
wolffd@0
|
245 elseif ~isempty(Traj.secondary_data) ...
|
wolffd@0
|
246 & size1~= size2
|
wolffd@0
|
247 % If data1 and data2 exist both, check data1 and data2 match
|
wolffd@0
|
248 error('''Data1'' and ''Data2'' have different amount of data vectors.')
|
wolffd@0
|
249 end
|
wolffd@0
|
250
|
wolffd@0
|
251 % Check BMU and data1 match (data2 matches with 1 anyway)
|
wolffd@0
|
252
|
wolffd@0
|
253 if ~isempty(Traj.primary_data) & size(bmus,1) ~= size1,
|
wolffd@0
|
254 error(['The number of data vectors in ''data1'' must match with' ...
|
wolffd@0
|
255 ' the number of rows in the first input argument (bmus).']);
|
wolffd@0
|
256 end
|
wolffd@0
|
257
|
wolffd@0
|
258 % Check that number of names and data dimension is consistent
|
wolffd@0
|
259
|
wolffd@0
|
260 if ~isempty(Traj.primary_names) & (size1(2)~=length(Traj.primary_names)),
|
wolffd@0
|
261 error('Number of component names and ''Data1'' dimension mismatch.');
|
wolffd@0
|
262 end
|
wolffd@0
|
263 if ~isempty(Traj.secondary_names) & ...
|
wolffd@0
|
264 (size2(2)~=length(Traj.secondary_names)),
|
wolffd@0
|
265 error('Number of component names and ''Data2'' dimension mismatch.');
|
wolffd@0
|
266 end
|
wolffd@0
|
267
|
wolffd@0
|
268 %% Call the function that does the job
|
wolffd@0
|
269 vis_trajgui(Traj);
|
wolffd@0
|
270
|
wolffd@0
|
271 %%% Subfunctions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
wolffd@0
|
272
|
wolffd@0
|
273 function Traj=iniTraj(bmus)
|
wolffd@0
|
274
|
wolffd@0
|
275 Traj.figure=gcf;
|
wolffd@0
|
276 Traj.primary_data=[];
|
wolffd@0
|
277 Traj.secondary_data=[];
|
wolffd@0
|
278 Traj.primary_names = [];
|
wolffd@0
|
279 Traj.secondary_names = [];
|
wolffd@0
|
280 Traj.size=[16 12 10 8 6 4]';
|
wolffd@0
|
281 Traj.bmus=bmus;
|
wolffd@0
|
282 Traj.color='xor';
|
wolffd@0
|
283 Traj.msize=[];
|
wolffd@0
|
284 Traj.lattice=[];
|
wolffd@0
|
285
|