source: issm/trunk-jpl/externalpackages/cm_and_cb_utilities/cmapping.m@ 11804

Last change on this file since 11804 was 11804, checked in by Mathieu Morlighem, 13 years ago

Added cm_and_cb_utilities, very usefull to mix colormaps

File size: 14.9 KB
Line 
1function RGB = cmapping(varargin)
2%CMAPPING Colormap linear mapping/interpolation.
3%
4% SYNTAX:
5% cmapping
6% cmapping(U)
7% cmapping(U,CMAP)
8% cmapping(U,CMAP,...,CNAN)
9% cmapping(U,CMAP,...,TYPE)
10% cmapping(U,CMAP,...,MODE)
11% cmapping(U,CMAP,...,MAPS)
12% cmapping(U,CMAP,...,CLIM)
13% cmapping(AX,...)
14% RGB = cmapping(...);
15%
16% INPUT:
17% U - May be one of the following options:
18% a) An scalar specifying the output M number of colors.
19% b) A vector of length M specifying the values at which
20% the function CMAP(IMAP) will be mapped.
21% c) A matrix of size M-by-N specifying intensities to be
22% mapped to an RGB (3-dim) image. May have NaNs elements.
23% DEFAULT: Current colormap length.
24% CMAP - A COLORMAP defined by its name or handle-function or RGB
25% matrix (with 3 columns) or by a combination of colors chars
26% specifiers ('kbcw', for example) to be mapped. See NOTE below
27% for more options.
28% DEFAULT: Current colormap
29% CNAN - Color for NaNs values on U, specified by a 1-by-3 RGB color
30% or a char specifier.
31% DEFAULT: Current axes background (white color: [1 1 1])
32% TYPE - String specifying the result type. One of:
33% 'colormap' Forces a RGB colormap matrix result (3 columns)
34% 'image' Forces a RGB image result (3 dimensions)
35% DEFAULT: 'image' if U is a matrix, otherwise is 'colormap'
36% MODE - Defines the mapping way. One of:
37% 'discrete' For discrete colors
38% 'continuous' For continuous color (interpolates)
39% DEFAULT: 'continuous' (interpolates between colors)
40% MAPS - Specifies the mapping type. One of (see NOTES below):
41% 'scaled' Scales mapping, also by using CLIM (as IMAGESC).
42% 'direct' Do not scales the mapping (as IMAGE).
43% DEFAULT: 'scaled' (uses CLIM)
44% CLIM - Two element vector that, if given, scales the mapping within
45% this color limits. Ignored if 'direct' is specified.
46% DEFAULT: [0 size(CMAP,1)] or [0 1].
47% AX - Uses specified axes or figure handle to set/get the colormap.
48% If used, must be the first input.
49% DEFAULT: gca
50%
51% OUTPUT (all optional):
52% RGB - If U is not a matrix, this is an M-by-3 colormap matrix with
53% RGB colors in its rows, otherwise is an RGB image: M-by-N-by-3,
54% with the color red intensities defined by RGB(:,:,1), the green
55% ones by RGB(:,:,2) and the blue ones by RGB(:,:,3).
56%
57% DESCRIPTION:
58% This functions has various functionalities like: colormap generator,
59% colormap expansion/contraction, color mapping/interpolation, matrix
60% intensities convertion to RGB image, etc.
61%
62% The basic idea is a linear mapping between the CMAP columns
63% [red green blue] and the U data, ignoring its NaNs.
64%
65% NOTE:
66% * Optional inputs use its DEFAULT value when not given or [].
67% * Optional outputs may or not be called.
68% * If a single value of U is required for interpolation, use [U U].
69% * If the char '-' is used before the CMAP name, the colors will be
70% flipped. The same occurs if U is a negative integer.
71%
72% EXAMPLE:
73% % Colormaps:
74% figure, cmapping( 256,'krgby') , colorbar
75% figure, cmapping(-256,'krgby' ,'discrete'), colorbar
76% figure, cmapping(log(1:100),[],'discrete'), colorbar
77% % Images:
78% u = random('chi2',2,20,30); u(15:16,7:9) = NaN;
79% u = peaks(30); u(15:16,7:9) = NaN;
80% v = cmapping(u,jet(64),'discrete','k');
81% w = cmapping(u,cmapping(log(0:63),'jet','discrete'),'discrete');
82% figure, imagesc(u), cmapping(64,'jet'), colorbar
83% title('u')
84% figure, imagesc(v), cmapping(64,'jet'), colorbar
85% title('u transformed to RGB (look the colored NaNs)')
86% figure, imagesc(w) ,cmapping(64,'jet'), colorbar
87% title('u mapped with log(colormap)')
88% figure, imagesc(u), cmapping(log(0:63),'jet','discrete'), colorbar
89% title('u with log(colormap)')
90%
91% SEE ALSO:
92% COLORMAP, IND2RGB
93% and
94% CMJOIN by Carlos Vargas
95% at http://www.mathworks.com/matlabcentral/fileexchange
96%
97%
98% ---
99% MFILE: cmapping.m
100% VERSION: 1.1 (Sep 02, 2009) (<a href="matlab:web('http://www.mathworks.com/matlabcentral/fileexchange/authors/11258')">download</a>)
101% MATLAB: 7.7.0.471 (R2008b)
102% AUTHOR: Carlos Adrian Vargas Aguilera (MEXICO)
103% CONTACT: nubeobscura@hotmail.com
104
105% REVISIONS:
106% 1.0 Released. (Jun 08, 2009)
107% 1.0.1 Fixed little bug with 'm' magenta color. (Jun 30, 2009)
108% 1.1 Fixed BUG with empty CMAP, thanks to Andrea Rumazza. (Sep 02,
109% 2009)
110
111% DISCLAIMER:
112% cmapping.m is provided "as is" without warranty of any kind, under the
113% revised BSD license.
114
115% Copyright (c) 2009 Carlos Adrian Vargas Aguilera
116
117
118% INPUTS CHECK-IN
119% -------------------------------------------------------------------------
120
121% Sets defaults:
122AX = {}; % Calculated inside.
123U = []; % Calculated inside.
124CMAP = []; % Calculated inside.
125TYPE = 'colormap'; % Changes to 'image' if U is a matrix.
126CLIM = []; % To use in scaling
127CNAN = [1 1 1]; % White 'w'
128MODE = 'continuous'; % Scaling to CLIM
129MAPS = 'scaled'; % Scaled mapping
130method = 'linear'; % Interpolation method
131mflip = false; % Flip the colormap
132
133% Gets figure handle and axes handle (just in case the default colormap or
134% background color axes will be used.
135HF = get(0,'CurrentFigure');
136HA = [];
137if ~isempty(HF)
138 HA = get(HF,'CurrentAxes');
139 if ~isempty(HA)
140 CNAN = get(HA,'Color'); % NaNs colors
141 end
142end
143
144% Checks inputs:
145if nargin>8
146 error('CVARGAS:cmapping:tooManyInputs', ...
147 'At most 8 inputs are allowed.')
148elseif nargout>1
149 error('CVARGAS:cmapping:tooManyOutputs', ...
150 'At most 1 output is allowed.')
151end
152
153% Checks AX:
154if (~isempty(varargin)) && ~isempty(varargin{1}) && ...
155 (numel(varargin{1})==1) && ishandle(varargin{1}) && ...
156 strcmp(get(varargin{1},'Type'),'axes')
157 % Gets AX and moves all other inputs to the left:
158 AX = varargin(1);
159 HA = AX{1};
160 CNAN = get(HA,'Color');
161 varargin(1) = [];
162end
163
164% Checks U:
165Nargin = length(varargin);
166if ~isempty(varargin)
167 U = varargin{1};
168 varargin(1) = [];
169end
170
171% Checks CMAP:
172if ~isempty(varargin)
173 CMAP = varargin{1};
174 varargin(1) = [];
175end
176
177% Checks input U, if not given uses as default colormap length:
178% Note: it is not converted to a vector in case CMAP is a function and IMAP
179% was not given.
180if isempty(U)
181 % Gets default COLORMAP length:
182 if ~isempty(HA)
183 U = size(colormap(HA),1);
184 else
185 U = size(get(0,'DefaultFigureColormap'),1);
186 end
187elseif ndims(U)>2
188 error('CVARGAS:cmapping:incorrectXInput', ...
189 'U must be an scalar, a vector or a 2-dimensional matrix.')
190end
191
192% Checks input CMAP:
193if isempty(CMAP)
194 % CMAP empty, then uses default:
195 if ~isempty(HA)
196 CMAP = colormap(HA);
197 if isempty(CMAP) % Fixed BUG, Sep 2009.
198 CMAP = get(0,'DefaultFigureColormap');
199 if isempty(CMAP)
200 CMAP = jet(64);
201 end
202 end
203 else
204 CMAP = get(0,'DefaultFigureColormap');
205 if isempty(CMAP)
206 CMAP = jet(64);
207 end
208 end
209 Ncmap = size(CMAP,1);
210elseif isnumeric(CMAP)
211 % CMAP as an [R G B] colormap:
212 Ncmap = size(CMAP,1);
213 if (size(CMAP,2)~=3) || ...
214 ((min(CMAP(:))<0) || (max(CMAP(:))>1)) || any(~isfinite(CMAP(:)))
215 error('CVARGAS:cmapping:incorrectCmapInput', ...
216 'CMAP is an incorrect 3 columns RGB colors.')
217 end
218elseif ischar(CMAP)
219 % String CMAP
220 % Checks first character:
221 switch CMAP(1)
222 case '-'
223 mflip = ~mflip;
224 CMAP(1) = [];
225 if isempty(CMAP)
226 error('CVARGAS:cmapping:emptyCmapInput',...
227 'CMAP function is empty.')
228 end
229 end
230 if ~((exist(CMAP,'file')==2) || (exist(CMAP,'builtin')==5))
231 % CMAP as a combination of color char specifiers:
232 CMAP = lower(CMAP);
233 iy = (CMAP=='y');
234 im = (CMAP=='m');
235 ic = (CMAP=='c');
236 ir = (CMAP=='r');
237 ig = (CMAP=='g');
238 ib = (CMAP=='b');
239 iw = (CMAP=='w');
240 ik = (CMAP=='k');
241 Ncmap = length(CMAP);
242 if (sum([iy im ic ir ig ib iw ik])~=Ncmap)
243 error('CVARGAS:cmapping:incorrectCmapStringInput', ...
244 ['String CMAP must be a valid colormap name or a combination of '...
245 '''ymcrgbwk''.'])
246 end
247 % Convertion to [R G B]:
248 CMAP = zeros(Ncmap,3);
249 CMAP(iy,:) = repmat([1 1 0],sum(iy),1);
250 CMAP(im,:) = repmat([1 0 1],sum(im),1); % BUG fixed Jun 2009
251 CMAP(ic,:) = repmat([0 1 1],sum(ic),1);
252 CMAP(ir,:) = repmat([1 0 0],sum(ir),1);
253 CMAP(ig,:) = repmat([0 1 0],sum(ig),1);
254 CMAP(ib,:) = repmat([0 0 1],sum(ib),1);
255 CMAP(iw,:) = repmat([1 1 1],sum(iw),1);
256 CMAP(ik,:) = repmat([0 0 0],sum(ik),1);
257 else
258 % CMAP as a function name
259 % Changes function name to handle:
260 CMAP = str2func(CMAP);
261 Ncmap = []; % This indicates a CMAP function input
262 end
263elseif isa(CMAP,'function_handle')
264 Ncmap = []; % This indicates a CMAP function input
265else
266 % CMAP input unrecognized:
267 error('CVARGAS:cmapping:incorrectCmapInput', ...
268 'Not recognized CMAP input.')
269end
270
271% Checks CMAP function handle:
272if isempty(Ncmap)
273 % Generates the COLORMAP from function:
274 try
275 temp = CMAP(2);
276 if ~all(size(temp)==[2 3]) || any(~isfinite(temp(:))), error(''), end
277 clear temp
278 catch
279 error('CVARGAS:cmapping:incorrectCmapFunction', ...
280 ['CMAP function ''' func2str(CMAP) ''' must result in RGB colors.'])
281 end
282end
283
284% Checks varargin:
285while ~isempty(varargin)
286 if isempty(varargin{1})
287 % continue
288 elseif ischar(varargin{1})
289 % string input
290 switch lower(varargin{1})
291 % CNAN:
292 case 'y' , CNAN = [1 1 0];
293 case 'm' , CNAN = [1 0 0];
294 case 'c' , CNAN = [0 1 1];
295 case 'r' , CNAN = [1 0 0];
296 case 'g' , CNAN = [0 1 0];
297 case 'b' , CNAN = [0 0 1];
298 case 'w' , CNAN = [1 1 1];
299 case 'k' , CNAN = [0 0 0];
300 % MODE:
301 case 'discrete' , MODE = 'discrete';
302 case 'continuous', MODE = 'continuous';
303 % TYPE:
304 case 'colormap' , TYPE = 'colormap';
305 case 'image' , TYPE = 'image';
306 % MAPS:
307 case 'direct' , MAPS = 'direct';
308 case 'scaled' , MAPS = 'scaled';
309 % Incorrect input:
310 otherwise
311 error('CVARGAS:cmapping:incorrectStringInput',...
312 ['Not recognized optional string input: ''' varargin{1} '''.'])
313 end
314 elseif isnumeric(varargin{1}) && all(isfinite(varargin{1}(:)))
315 % numeric input
316 nv = numel(varargin{1});
317 if (nv==3) && (size(varargin{1},1)==1)
318 % CNAN:
319 CNAN = varargin{1}(:)';
320 if (max(CNAN)>1) || (min(CNAN)<0)
321 error('CVARGAS:cmapping:incorrectCnanInput',...
322 'CNAN elements must be between 0 and 1.')
323 end
324 elseif (nv==2) && (size(varargin{1},1)==1)
325 % CLIM:
326 CLIM = sort(varargin{1},'ascend');
327 if (diff(CLIM)==0)
328 error('CVARGAS:cmapping:incorrectClimValues',...
329 'CLIM must have 2 distint elements.')
330 end
331 else
332 error('CVARGAS:cmapping:incorrectNumericInput',...
333 'Not recognized numeric input.')
334 end
335 else
336 error('CVARGAS:cmapping:incorrectInput',...
337 'Not recognized input.')
338 end
339 % Clears current optional input:
340 varargin(1) = [];
341end % while
342
343
344% -------------------------------------------------------------------------
345% MAIN
346% -------------------------------------------------------------------------
347
348% U size:
349[m,n] = size(U);
350mn = m*n;
351
352% Checks TYPE:
353if ~any([m n]==1)
354 % Forces image TYPE if U is a matrix:
355 TYPE = 'image';
356elseif strcmp(TYPE,'colormap') && ~nargout && isempty(AX)
357 % Changes the colormap on the specified or current axes if no output
358 % argument:
359 AX = {gca};
360end
361
362% Forces positive integer if U is an scalar, and flips CMAP if is negative:
363if (mn==1)
364 U = round(U);
365 if (U==0)
366 if ~nargout && strcmp(TYPE,'colormap')
367 warning('CVARGAS:cmapping:incorrectUInput',...
368 'U was zero and produces no colormap')
369 else
370 RGB = [];
371 end
372 return
373 elseif (U<0)
374 mflip = ~mflip;
375 U = abs(U);
376 end
377end
378
379% Gets CMAP from function handle:
380if isempty(Ncmap)
381 if (mn==1)
382 % From U:
383 Ncmap = U(1);
384 else
385 % From default colormap:
386 if ~isempty(HA)
387 Ncmap = size(colormap(HA),1);
388 else
389 Ncmap = size(get(0,'DefaultFigureColormap'),1);
390 end
391 end
392 CMAP = CMAP(Ncmap);
393end
394
395% Flips the colormap
396if mflip
397 CMAP = flipud(CMAP);
398end
399
400% Check CMAP when U is an scalar::
401if (mn==1) && (U==Ncmap)
402 % Finishes:
403 if ~nargout && strcmp(TYPE,'colormap')
404 if Nargin==0
405 RGB = colormap(AX{:},CMAP);
406 else
407 colormap(AX{:},CMAP)
408 end
409 else
410 RGB = CMAP;
411 if strcmp(TYPE,'image')
412 RGB = reshape(RGB,Ncmap,1,3);
413 end
414 end
415 return
416end
417
418% Sets scales:
419if strcmp(MAPS,'scaled')
420 % Scaled mapping:
421 if ~isempty(CLIM)
422 if (mn==1)
423 mn = U;
424 U = linspace(CLIM(1),CLIM(2),mn)';
425 else
426 % Continue
427 end
428 else
429 CLIM = [0 1];
430 if (mn==1)
431 mn = U;
432 U = linspace(CLIM(1),CLIM(2),mn)';
433 else
434 % Scales U to [0 1]:
435 U = U-min(U(isfinite(U(:))));
436 U = U/max(U(isfinite(U(:))));
437 % Scales U to CLIM:
438 U = U*diff(CLIM)+CLIM(1);
439 end
440 end
441else
442 % Direct mapping:
443 CLIM = [1 Ncmap];
444end
445
446% Do not extrapolates:
447U(U<CLIM(1)) = CLIM(1);
448U(U>CLIM(2)) = CLIM(2);
449
450% Sets CMAP argument:
451umap = linspace(CLIM(1),CLIM(2),Ncmap)';
452
453% Sets U:
454if (mn==2) && (U(1)==U(2))
455 % U = [Uo Uo] implicates U = Uo:
456 U(2) = [];
457 mn = 1;
458 m = 1;
459 n = 1;
460end
461
462% Sets discretization:
463if strcmp(MODE,'discrete')
464 umap2 = linspace(umap(1),umap(end),Ncmap+1)';
465 for k = 1:Ncmap
466 U((U>umap2(k)) & (U<=umap2(k+1))) = umap(k);
467 end
468 clear umap2
469end
470
471% Forces column vector:
472U = U(:);
473
474% Gets finite data:
475inan = ~isfinite(U);
476
477% Initializes:
478RGB = repmat(reshape(CNAN,[1 1 3]),[mn 1 1]);
479
480% Interpolates:
481if (Ncmap>1) && (sum(~inan)>1)
482 [Utemp,a,b] = unique(U(~inan));
483 RGBtemp = [...
484 interp1(umap,CMAP(:,1),Utemp,method) ...
485 interp1(umap,CMAP(:,2),Utemp,method) ...
486 interp1(umap,CMAP(:,3),Utemp,method) ...
487 ];
488 RGB(~inan,:) = RGBtemp(b,:);
489else
490 % single color:
491 RGB(~inan,1,:) = repmat(reshape(CMAP,[1 1 3]),[sum(~inan) 1 1]);
492end
493
494% Just in case
495RGB(RGB>1) = 1;
496RGB(RGB<0) = 0;
497
498% OUTPUTS CHECK-OUT
499% -------------------------------------------------------------------------
500
501% Output type:
502if strcmp(TYPE,'colormap')
503 RGB = reshape(RGB,mn,3);
504 if ~isempty(AX)
505 colormap(AX{:},RGB)
506 if ~nargout
507 clear RGB
508 end
509 end
510else
511 RGB = reshape(RGB,[m n 3]);
512end
513
514
515% [EOF] cmapping.m
Note: See TracBrowser for help on using the repository browser.