diff --git a/imagescnan.m b/imagescnan.m
new file mode 100644
index 0000000..e88523c
--- /dev/null
+++ b/imagescnan.m
@@ -0,0 +1,477 @@
+function [H,HNAN] = imagescnan(varargin)
+%IMAGESCNAN Scale data and display as image with uncolored NaNs.
+%
+% SYNTAX:
+% imagescnan(U)
+% imagescnan(U,...,'NanColor',CNAN)
+% imagescnan(U,...,'NanMask',MNAN)
+% imagescnan(U,...,IOPT)
+% imagescnan(X,Y,U,...)
+% [H,HNAN] = imagescnan(...);
+%
+% INPUT:
+% U - 2 dimensional N-by-M image or N-by-M-by-3 RGB image.
+% X - 2 extrema X-axis data; or the M values; or the N-by-M values
+% as obtained from MESHGRID (see DESCRIPTION below).
+% DEFAULT: [1 N]
+% Y - 2 extrema X-axis data; or the N values; or the N-by-M values
+% as obtained from MESHGRID (see DESCRIPTION below).
+% DEFAULT: [1 M]
+% CNAN - Color for the NaNs elements. May be a char specifier or an [R
+% G B] triplet specifying the color.
+% DEFAULT: invisible (axes background color)
+% MNAN - Elements to be ignored besides not finite values. May be an
+% scalar or a logical M-by-N matrix indicating the elements to
+% be ignored.
+% DEFAULT: []
+% IOPT - IMAGE function normal optional pair arguments like
+% ('Parent',H) or/and CLIM like optional last argument as in
+% IMAGESC.
+% DEFAULT: none
+%
+% OUTPUT (all optional):
+% H - Image handle
+% HNAN - Handle of every ignored (NaN) value colored patch.
+%
+% DESCRIPTION:
+% MATLAB function IMAGESC does not work properly with NaNs. This
+% programs deals with this problem by including colored patches over
+% this elements and maybe others specyfied by the user with MNAN.
+%
+% Besides, those functions does not work properly with X,Y values
+% variable interval, but this functions does it by generating a whole
+% new image of several rectangular patches, but whose centers may not
+% lay in the specified coordinate (see NOTE below). This functionality
+% is experimental and not recommended (see ADDITIONAL NOTES inside this
+% program).
+%
+% In previous release, 2-dim input images were transformed into a
+% 3-dim RGB image. This is not used anymore (see ADDITIONAL NOTES
+% inside this file).
+%
+% NOTE:
+% * Optional inputs use its DEFAULT value when not given or [].
+% * Optional outputs may or not be called.
+% * If X is a two element vector, min(X) will be the coordinate of the
+% first column and max(X) of the last column.
+% * If Y is a two element vector, min(Y) will be the coordinate of the
+% first row and max(Y) of the last row.
+% * If vector X-axis is decreasing U=fliplr(U) will be used.
+% * If vector Y-axis is decreasing U=flipud(U) will be used.
+% * When X or Y do not have a constant increasing/decreasing step, the
+% vertices of the color rectangules are set in the middle of each
+% pair of coordinates. For this reason its center may not lay on the
+% specified coordinate, except on the coordinates at the edges where
+% it always lays on the center.
+% * To get a non-scaled image (IMAGE instead of IMAGESC) use:
+% >> H = imagescnan(...);
+% >> set(H,'CDataMapping','direct')
+% * ADDITIONAL NOTES are included inside this file.
+%
+% EXAMPLE:
+% % Compares with normal IMAGESC:
+% N = 100;
+% PNaNs = 0.10;
+% U = peaks(N);
+% U(round(1 + (N^2-1).*rand(N^2*PNaNs,1))) = NaN; % Adds NaNs
+% subplot(221), imagesc(U)
+% title('With IMAGESC: ugly NaNs')
+% subplot(222), imagescnan(U)
+% title('With IMAGESCNAN: uncolored NaNs')
+% % Compares with SPY:
+% subplot(223), spy(isnan(U))
+% title('SPY(isnan(U))')
+% subplot(224), imagescnan(isnan(U),'NaNMask',0), axis equal tight
+% title('SPY with IMAGESCNAN')
+%
+% SEE ALSO:
+% IMAGE, IMAGESC, COLORBAR, IMREAD, IMWRITE
+% and
+% CMAPPING, CBFREEZE by Carlos Vargas
+% at http://www.mathworks.com/matlabcentral/fileexchange
+%
+%
+% ---
+% MFILE: imagescnan.m
+% VERSION: 2.1 (Aug 20, 2009) (download)
+% MATLAB: 7.7.0.471 (R2008b)
+% AUTHOR: Carlos Adrian Vargas Aguilera (MEXICO)
+% CONTACT: nubeobscura@hotmail.com
+
+% ADDITIONAL NOTES:
+% * I keep getting a kind of BUG with the edges of the patched NaNs. I
+% added two NOTE inside this program that may fix this problem.
+% Another way is to convert the intensity matrix U into RGB colors by
+% using the CMAPPING function, as used by the first version of this
+% program.
+% * Besides, if the matrix is too large, sometimes there is an
+% undocumented failure while drawing the patch NaNs. Is recommended
+% to use U = cmapping(U,[],'k','discrete') instead, and change the
+% CLIM to [min(U(:)) max(U(:))].
+% * The use of not homogeneous step interval X,Y axes is not
+% recommended because the program tries to put its value in the
+% middle of the colored rectangule (as IMAGESC does) and soetimes the
+% result may not be what the user wants. So this is for experimental
+% use only.
+
+% REVISIONS:
+% 1.0 Released. (Jun 30, 2008)
+% 1.1 Fixed bug when CAXIS used. Colorbar freezed colormap. Fixed
+% bug in color vector input (Found by Greg King) and now
+% accets RGB image as input. (Jul 14, 2008)
+% 2.0 Totally rewritten code. Do not converts to RGB anymore. Do not
+% freezes the colormap anymore. Do not output any colorbar. New
+% X and Y variable steps accepted input. Now uses patches. (Jun
+% 08, 2009)
+% 2.1 Fixed bug with RGB input. Added a NOTE about the use of
+% CMAPPING. (Aug 20, 2009)
+
+% DISCLAIMER:
+% imagescnan.m is provided "as is" without warranty of any kind, under
+% the revised BSD license.
+
+% Copyright (c) 2008,2009 Carlos Adrian Vargas Aguilera
+
+
+% INPUTS CHECK-IN
+% -------------------------------------------------------------------------
+
+% Initializes:
+X = [];
+Y = [];
+CNAN = [];
+MNAN = [];
+ha = [];
+
+% Checks number of inputs:
+if nargin<1
+ error('CVARGAS:imagescnan:notEnoughInputs',...
+ 'At least 1 input is required.')
+elseif nargout>2
+ error('CVARGAS:imagescnan:tooManyOutputs',...
+ 'At most 2 outputs are allowed.')
+end
+
+% Gets X,Y,U:
+if ((nargin==1) || (nargin==2))
+ U = varargin{1};
+ varargin(1) = [];
+else
+ if (isnumeric(varargin{1}) && isnumeric(varargin{2}) && ...
+ isnumeric(varargin{3}))
+ X = varargin{1};
+ Y = varargin{2};
+ U = varargin{3};
+ varargin(1:3) = [];
+ else
+ U = varargin{1};
+ varargin(1) = [];
+ end
+end
+
+% Check U:
+ndim = ndims(U);
+if (ndim==2)
+ [M,N] = size(U);
+ O = 1;
+elseif (ndim==3)
+ [M,N,O] = size(U);
+ if (O~=3)
+ error('CVARGAS:imagescnan:incorrectRgbImage',...
+ 'RGB image must be of size M-by-N-by-3.')
+ end
+else
+ error('CVARGAS:imagescnan:incorrectImageSize',...
+ 'Image must be 2-dimensional or a 3-dim RGB image.')
+end
+
+% Check X:
+aequal = true; % Equal intervals on x-axis?
+dX = [];
+if isempty(X)
+ X = [1 N];
+else
+ if (ndims(X)>2)
+ error('CVARGAS:imagescnan:incorrectXDims',...
+ 'X must be a vector or a matrix as a result of MESHGRID.')
+ end
+ if any(~isfinite(X(:)))
+ error('CVARGAS:imagescnan:incorrectXValue',...
+ 'X elements must be numeric and finite.')
+ end
+ [Mx,Nx] = size(X);
+ if ((Mx*Nx)==2)
+ if X(2)(eps*max(abs(dX(:)))*1000))
+ error('CVARGAS:imagescnan:incorrectXMatrix',...
+ 'X matrix must be as generated by MESHGRID.')
+ end
+ X = X(1,:);
+ elseif (~any([Mx Nx]==1) && ~((Mx*Nx)==N))
+ error('CVARGAS:imagescnan:incorrectXSize',...
+ 'X must be an scalar or a matrix.')
+ end
+ % Forces ascending x-axis:
+ [X,I] = sort(X(:).');
+ for k = 1:O % Fixed bug Aug 2009
+ U(:,:,k) = U(:,I,k);
+ end
+ clear I
+ % Checks equal intervals:
+ dX = diff(X);
+ if any(abs(dX(1)-dX(2:end))>(eps*max(dX)*1000))
+ if aequal
+ aequal = false;
+ end
+ else
+ X = [X(1) X(end)];
+ dX = [];
+ end
+ end
+end
+
+% Check Y:
+dY = [];
+if isempty(Y)
+ Y = [1 M];
+else
+ if (ndims(Y)>2)
+ error('CVARGAS:imagescnan:incorrectYDims',...
+ 'Y must be a vector or a matrix as a result of MESHGRID.')
+ end
+ if any(~isfinite(Y(:)))
+ error('CVARGAS:imagescnan:incorrectYValue',...
+ 'Y elements must be numeric and finite.')
+ end
+ [My,Ny] = size(Y);
+ if ((My*Ny)==2)
+ if Y(2)(eps*max(abs(dY(:)))*1000))
+ error('CVARGAS:imagescnan:incorrectYMatrix',...
+ 'Y matrix must be as generated by MESHGRID.')
+ end
+ Y = Y(:,1);
+ elseif (~any([My Ny]==1) && ~((My*Ny)==M))
+ error('CVARGAS:imagescnan:incorrectYSize',...
+ 'Y must be an scalar or a matrix.')
+ end
+ % Forces ascending y-axis:
+ [Y,I] = sort(Y(:).');
+ for k = 1:O % Fixed bug Aug 2009
+ U(:,:,k) = U(I,:,k);
+ end
+ clear I
+ % Checks equal intervals:
+ dY = diff(Y);
+ if any(abs(dY(1)-dY(2:end))>(eps*max(dY)*1000))
+ if aequal
+ aequal = false;
+ end
+ else
+ Y = [Y(1) Y(end)];
+ dY = [];
+ end
+ end
+end
+
+% Checks varargin:
+ind = [];
+Nopt = length(varargin);
+for k = 1:Nopt-1
+ if (~isempty(varargin{k}) && ischar(varargin{k}))
+ if strncmpi(varargin{k},'NanColor',4)
+ CNAN = varargin{k+1};
+ ind = [ind k k+1];
+ elseif strncmpi(varargin{k},'NanMask',4)
+ MNAN = varargin{k+1};
+ ind = [ind k k+1];
+ elseif (strncmpi(varargin{k},'Parent',2) && isempty(CNAN))
+ try
+ CNAN = get(varargin{k+1},'Color');
+ ha = varargin{k+1};
+ catch
+ error('CVARGAS:imagescnan:incorrectParentHandle',...
+ '''Parent'' must be a valid axes handle.')
+ end
+ end
+ end
+end
+varargin(ind) = [];
+Nargin = length(varargin);
+
+% Check ha:
+if isempty(ha)
+ ha = gca;
+end
+
+% Check CNAN:
+if isempty(CNAN)
+ CNAN = get(ha,'Color');
+elseif ischar(CNAN)
+ switch lower(CNAN)
+ case 'y', CNAN = [1 1 0];
+ case 'm', CNAN = [1 0 0];
+ case 'c', CNAN = [0 1 1];
+ case 'r', CNAN = [1 0 0];
+ case 'g', CNAN = [0 1 0];
+ case 'b', CNAN = [0 0 1];
+ case 'w', CNAN = [1 1 1];
+ case 'k', CNAN = [0 0 0];
+ otherwise
+ error('CVARGAS:imagescnan:incorrectNancString',...
+ 'Color string must be a valid color identifier. One of ''ymcrgbwk''.')
+ end
+elseif isnumeric(CNAN) && (length(CNAN)==3)
+ CNAN = CNAN(:).'; % Forces row vector.
+else
+ error('CVARGAS:imagescnan:incorrectNancInput',...
+ 'Not recognized CNAN input.')
+end
+
+% Check MNAN:
+if isempty(MNAN)
+ MNAN = any(~isfinite(U),3);
+else
+ if (ndims(MNAN)==2)
+ [Mm,Nm] = size(MNAN);
+ if ((Mm*Nm)==1)
+ MNAN = (any(~isfinite(U),3) | any(U==MNAN,3));
+ elseif ((Mm==M) && (Nm==N) && islogical(MNAN))
+ MNAN = (any(~isfinite(U),3) | MNAN);
+ else
+ error('CVARGAS:imagescnan:incorrectNanmSize',...
+ 'MNAN must be an scalar or a logical matrix of size M-by-N.')
+ end
+ else
+ error('CVARGAS:imagescnan:incorrectNanmDims',...
+ 'MNAN must be an scalar or a matrix.')
+ end
+end
+
+% -------------------------------------------------------------------------
+% MAIN
+% -------------------------------------------------------------------------
+
+% Generates the image:
+if aequal
+ % IMAGESC way.
+ H = imagesc(X,Y,U,varargin{:});
+
+else
+ % PATCH way.
+
+ % Check clim:
+ if (rem(Nargin,2)==1)
+ clim = varargin{end};
+ varargin(end) = [];
+ if ((length(clim)~=2) || (clim(1)>clim(2)))
+ error('CVARGAS:imagescnan:incorrectClimInput',...
+ 'clim must be a 2 element increasing vector.')
+ end
+ else
+ clim = [];
+ end
+
+ % Generates vertices between coordinates (coordinates may not be at the
+ % center of these vertices):
+ if (length(X)~=N)
+ X = (0:N-1)*((X(2)-X(1))/(N-1)) + X(1);
+ end
+ if (length(Y)~=M)
+ Y = (0:M-1)*((Y(2)-Y(1))/(M-1)) + Y(1);
+ end
+ if isempty(dX)
+ dX = diff(X);
+ end
+ if isempty(dY)
+ dY = diff(Y);
+ end
+ [X,Y] = meshgrid([X(1)-dX(1)/2 X+dX([1:N-1 N-1])/2],...
+ [Y(1)-dY(1)/2 Y+dY([1:M-1 M-1])/2]);
+
+ % Generates faces:
+ ind = (1:(M+1)*N)';
+ ind(M+1:M+1:end) = [];
+
+ % Generates patches:
+ H = patch(...
+ 'Vertices' ,[X(:) Y(:)],...
+ 'Faces' ,[ind ind+1 ind+M+2 ind+M+1],...
+ 'FaceVertexCData',U(:),...
+ 'FaceColor' ,'flat',...
+ 'EdgeColor' ,'none',... % NOTE: Sometimes this is not required.
+ varargin{:});
+ set(ha,...
+ 'YDir' ,'reverse',...
+ 'View' ,[0 90],...
+ 'Box' ,'on',...
+ 'Layer','top')
+ axis(ha,'tight')
+
+ % Sets clim:
+ if ~isempty(clim)
+ set(ha,'CLim',clim)
+ else
+ set(ha,'CLimMode','auto')
+ end
+
+end
+
+% Adds NaNs patches:
+if any(MNAN(:))
+ if aequal
+ % dX and dY is constant:
+ [MNAN,NNAN] = ind2sub([M,N],find(MNAN));
+ Nnan = length(MNAN);
+ dX = (X(2)-X(1))/(N-1)/2;
+ dY = (Y(2)-Y(1))/(M-1)/2;
+ HNAN = patch(repmat((X(1)+(NNAN(:)'-1)*(2*dX)),4,1) + ...
+ (repmat([-1 1 1 -1]'*dX,1,Nnan)),...
+ repmat((Y(1)+(MNAN(:)'-1)*(2*dY)),4,1) + ...
+ (repmat([1 1 -1 -1]'*dY,1,Nnan)),...
+ CNAN,...
+ 'EdgeColor',CNAN,... 'EdgeColor','none',...
+ varargin{1:Nargin-rem(Nargin,2)});
+ else
+ % dX and/or dY is not constant:
+ MNAN = find(MNAN);
+ HNAN = patch(...
+ 'Vertices' ,[X(:) Y(:)],...
+ 'Faces' ,[ind(MNAN) ind(MNAN)+1 ind(MNAN)+M+2 ind(MNAN)+M+1],...
+ 'FaceColor' ,CNAN,...
+ 'EdgeColor' ,'none',... 'EdgeColor',CNAN,... % NOTE: may be better?
+ varargin{:});
+ end
+else
+ HNAN = [];
+end
+
+
+% OUTPUTS CHECK-OUT
+% -------------------------------------------------------------------------
+
+% Clears outputs?:
+if (nargout==0)
+ clear H
+end
+
+
+% [EOF] imagescnan.m
\ No newline at end of file