Home > utilities > quiverwcolorbar.m

quiverwcolorbar

PURPOSE ^

Melissa Day 5/24/2013

SYNOPSIS ^

function hh = quiverwcolorbar(varargin)

DESCRIPTION ^

 Melissa Day 5/24/2013
 Upgrade of Andrew Diamond's quiverc2wcmap to generate a quiver plot
 with arrows colored according to vector magnitude. 
 Functional differences from quiverc2wcmap:
   1) Allows user to specify colormap boundaries using 'bound': changes 
      colorbar axes AND corresponding vector coloring
      (much more useful for intercomparison of datasets)
   2) Improved fidelity to magnitude colors in large datasets 
      (at a cost of increased computation time...)
      Uses some improvements from DS's vfield_color
   3) Small clarifications added
 Example:
             x = rand(1,50).*100;
             y = rand(1,50).*100;
             u = rand(1,50) .* 10;
             v = rand(1,50) .* 10;
             scale = 0;
             figure; quiverwcolorbar(x',y',u',v',scale); %compare to:
             figure; quiverwcolorbar(x',y',u',v',scale,'bounds',[0 10]);
----------------
 function hh = quiverc2wcmap(varargin)
 Andrew Diamond 3/17/2005
 This is based off of Tobias H�fken which was based off of Bertrand Dano
 keeping with their main intent to show a color w/r to magnitude quiver plot
 while maintaining a large amount of quiver API backwards compatability.
 Functional differences from quiverc2:
   1) This works under 6.5.1
   2) It handles NaNs
   3) It draws a colormap that is w/r to the quiver magnitudes (hard coded to
   20 segments of the colormap as per quiverc2 - seems fine for a quiver).
   4) Various bug fixes (I think)
 In order to do this I needed some small hacks on 6.5.1's quiver to take a
 color triplet.  I have included as part of this file in a subfunction below.
----------------
 Comments from quiverc2
 changed Tobias H�fken 3-14-05
 totally downstripped version of the former
 split input field into n segments and do a quiver qhich each of them

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001  function hh = quiverwcolorbar(varargin)
0002 % Melissa Day 5/24/2013
0003 % Upgrade of Andrew Diamond's quiverc2wcmap to generate a quiver plot
0004 % with arrows colored according to vector magnitude.
0005 % Functional differences from quiverc2wcmap:
0006 %   1) Allows user to specify colormap boundaries using 'bound': changes
0007 %      colorbar axes AND corresponding vector coloring
0008 %      (much more useful for intercomparison of datasets)
0009 %   2) Improved fidelity to magnitude colors in large datasets
0010 %      (at a cost of increased computation time...)
0011 %      Uses some improvements from DS's vfield_color
0012 %   3) Small clarifications added
0013 % Example:
0014 %             x = rand(1,50).*100;
0015 %             y = rand(1,50).*100;
0016 %             u = rand(1,50) .* 10;
0017 %             v = rand(1,50) .* 10;
0018 %             scale = 0;
0019 %             figure; quiverwcolorbar(x',y',u',v',scale); %compare to:
0020 %             figure; quiverwcolorbar(x',y',u',v',scale,'bounds',[0 10]);
0021 %----------------
0022 % function hh = quiverc2wcmap(varargin)
0023 % Andrew Diamond 3/17/2005
0024 % This is based off of Tobias H�fken which was based off of Bertrand Dano
0025 % keeping with their main intent to show a color w/r to magnitude quiver plot
0026 % while maintaining a large amount of quiver API backwards compatability.
0027 % Functional differences from quiverc2:
0028 %   1) This works under 6.5.1
0029 %   2) It handles NaNs
0030 %   3) It draws a colormap that is w/r to the quiver magnitudes (hard coded to
0031 %   20 segments of the colormap as per quiverc2 - seems fine for a quiver).
0032 %   4) Various bug fixes (I think)
0033 % In order to do this I needed some small hacks on 6.5.1's quiver to take a
0034 % color triplet.  I have included as part of this file in a subfunction below.
0035 %----------------
0036 % Comments from quiverc2
0037 % changed Tobias H�fken 3-14-05
0038 % totally downstripped version of the former
0039 % split input field into n segments and do a quiver qhich each of them
0040  
0041 % Modified version of Quiver to plots velocity vectors as arrows
0042 % with components (u,v) at the points (x,y) using the current colormap
0043 
0044 % Bertrand Dano 3-3-03
0045 % Copyright 1984-2002 The MathWorks, Inc.
0046 
0047 % changed T. H�fken 14.03.05, for high data resolution
0048 % using fixed color "spacing" of 20
0049 
0050 %QUIVERC Quiver color plot.
0051 %   QUIVERC(X,Y,U,V) plots velocity vectors as arrows with components (u,v)
0052 %   at the points (x,y).  The matrices X,Y,U,V must all be the same size
0053 %   and contain corresponding position and velocity components (X and Y
0054 %   can also be vectors to specify a uniform grid).  QUIVER automatically
0055 %   scales the arrows to fit within the grid.
0056 %
0057 %   QUIVERC(U,V) plots velocity vectors at equally spaced points in
0058 %   the x-y plane.
0059 %
0060 %   QUIVERC(U,V,S) or QUIVER(X,Y,U,V,S) automatically scales the
0061 %   arrows to fit within the grid and then stretches them by S.  Use
0062 %   S=0 to plot the arrows without the automatic scaling.
0063 %
0064 %   QUIVERC(...,LINESPEC) uses the plot linestyle specified for
0065 %   the velocity vectors.  Any marker in LINESPEC is drawn at the base
0066 %   instead of an arrow on the tip.  Use a marker of '.' to specify
0067 %   no marker at all.  See PLOT for other possibilities.
0068 %
0069 %   QUIVERC(...,'filled') fills any markers specified.
0070 %
0071 %   H = QUIVERC(...) returns a vector of line handles.
0072 %
0073 %   Example:
0074 %      [x,y] = meshgrid(-2:.2:2,-1:.15:1);
0075 %      z = x .* exp(-x.^2 - y.^2); [px,py] = gradient(z,.2,.15);
0076 %      contour(x,y,z), hold on
0077 %      quiverc(x,y,px,py), hold off, axis image
0078 %
0079 %   See also FEATHER, QUIVER3, PLOT.
0080 %   Clay M. Thompson 3-3-94
0081 %   Copyright 1984-2002 The MathWorks, Inc.
0082 %   $Revision: 5.21 $  $Date: 2002/06/05 20:05:16 $
0083 %-------------------------------------------------------------
0084 nin = nargin;            %number of inputs
0085 
0086 % error(nargchk(2,5,nin));
0087 error(nargchk(2,7,nin)); %added +2 to maxargs to account for 'bounds' add
0088 
0089 % Check numeric input arguments
0090 if nin<4,                % quiver(u,v) or quiver(u,v,s)
0091   [msg,x,y,u,v] = xyzchk(varargin{1:2});
0092 else                     % quiver(x,y,u,v) and beyond
0093   [msg,x,y,u,v] = xyzchk(varargin{1:4});
0094 end
0095 if ~isempty(msg), error(msg); end
0096 
0097 scale=1;                 % This is the default I think.
0098 if(nin == 3)  % quiver(u,v,s)
0099     if(isscalar(varargin{nin}))
0100         scale = varargin{nin};
0101     end
0102 elseif(nin >= 5)  % quiver(x,y,u,v,s) or quiver(x,y,u,v,s,'bounds',[start end])
0103     if(isscalar(varargin{5}))
0104         scale = varargin{5};
0105     end
0106 end
0107 
0108 %-------------Define matrix of vector magnitudes-------------
0109 % Define matrix of vector magnitudes
0110 vr = sqrt(u.^2+v.^2); 
0111 
0112 % From quiverc2wcmap:
0113 % if data has Nan, don't let it contaminate the computations that segment the
0114 % data;  I could just do this with vr and then get clever with the indices but
0115 % this make for easy debugging and as this is a graphics routine the computation
0116 % time is completely irrelevant.
0117 nonNaNind = find(~isnan(vr(:)));
0118 xyuvvrNN = [x(nonNaNind),y(nonNaNind),u(nonNaNind),v(nonNaNind),vr(nonNaNind)];
0119 [xyuvvrNNs, xyuvvrNNsi] = sortrows(xyuvvrNN,5);
0120 
0121 % From quiverc2wcmap, no longer necessary
0122 % n = 20; %number of colors
0123 % CC = colormap;
0124 % iCCs=round(linspace(1,size(CC,1),n));
0125 % iData = round(linspace(0,size(xyuvvrNNs,1),n+1));
0126 % figure;
0127 
0128 %-------------Generate colorbar-------------
0129 % Includes a clever way to generate (and subsequently hide) an image that
0130 % is required for colorbar without running out of memory for large datasets.
0131 %
0132 % Condensed comments from quiverc2wcmap:
0133 % In 6.5.1 if you ever want a colorbar tick marks to reflect real data ranges
0134 % (versus just the indices of a colormap) then there apparently has to be an
0135 % image somewhere in the figure.  Of course, I don't want an image but I figured
0136 % I just make it invisible and then draw the quiver plot over it.
0137 % Unfortunately, it seems that colorbar uses caxis to retrive the data range in
0138 % the image and for invisible images it always seems to be 0 UNLESS you
0139 % explictly reset the caxis.
0140 % This will work but then the axis will be oversized to accomodate the image
0141 % because images have their first and last vitual "pixels" CENTERED around the
0142 % implicit or explict xmin,xmax,ymin,ymax (as per imagesc documentation) but the
0143 % start and end of each of these "pixels" is +/- half a unit where the unit
0144 % corresponds to subdividing the limits by the number of pixels (-1).  Given
0145 % that formula and given my invisible 2x2 image for which it is desired to
0146 % diplay in an axis that ISN'T oversized (i.e. min(x), max(x), min(y),max(y)) it
0147 % is possible to solve for the limits (i.e. an artifically reduced limit)
0148 % that need to be specified for imagesc to make its final oversized axis to be the
0149 % non oversized axis that we really want.
0150 % xa,xb,ya,yb compenstates for the axis extention given by imagesc to make
0151 % pixels centered at the limit extents (etc.).  Note, this "easy"
0152 % formula would only work for 2x2 pixel images.
0153 
0154 xs = min(x);    %x(1);
0155 xf = max(x);    %x(end)
0156 xa = (3 * xs + xf)/4;
0157 xb = (3 * xf + xs)/4;
0158 ys = min(y);    %y(1);
0159 yf = max(y);    %y(end)
0160 ya = (3 * ys + yf)/4;
0161 yb = (3 * yf + ys)/4;
0162 
0163 % Determine magnitude min/max (which is reflected in colorbar)
0164 colormin = min(xyuvvrNNs(:,5));  %column 5 is NaN-cleared vr
0165 colormax = max(xyuvvrNNs(:,5));
0166 
0167 % Allow user to edit bounds using "'bounds',[colormin colormax]" input
0168 for k=1:nin
0169  if (k~=nin) && (length(varargin{k})==6) && strcmp(varargin{k},'bounds')
0170      bounds = varargin{k+1}; 
0171      if isempty(bounds), error('Specify colormap boundaries'); end
0172          colormin = bounds(1);
0173          colormax = bounds(2);
0174  end
0175 end
0176 % mapbounds = reshape(xyuvvrNNs([1,end;1,end],5),2,2); %from quiverc2wcmap
0177 mapbounds = [colormin colormax; colormin colormax];
0178 h=imagesc([xa,xb],[ya,yb],mapbounds);
0179 set(h,'visible','off');
0180 
0181 %   Prep colorbar
0182 rang = (colormax-colormin)/colormax;
0183 ticknum = 6;        %if you want to toggle number of ticks on colorbar
0184 incr = rang./(ticknum-1);
0185 B = [colormin/colormax:incr:1];
0186 B = B.*colormax;
0187 C = sprintf(['%4.2e',repmat([' \n%4.2e'], 1, ticknum)],B);
0188 C = str2num(C);
0189 caxis([colormin colormax])
0190 colorbar('EastOutside','ytick',B,'yticklabel',C,...
0191     'ticklength',[0.04 0.1],'YLim',[B(1) B(ticknum)],'FontSize',20)
0192 
0193 % In quiverc2wcmap this loop plotted for each color level (n=20) and was very
0194 % fast, but I found it did not plot some large data sets with enough color
0195 % accuracy.  Switched the loop to examine each data point individually.
0196 % Takes longer but I'm more confident that the colors are correct. Note:
0197 % much of this overhaul was inspired by DS's vfield_color.
0198 hold on;
0199 cmap = jet(64);     %toggle type of colormap
0200 CC = colormap(cmap);
0201 cm_stepsize = (colormax-colormin)/length(CC);
0202 for it=1:size(xyuvvrNNs,1)  %takes ~13 seconds for a 8730-point dataset
0203 % Some quiverc2wcmap fragments for reference:
0204 % for it=1:n %10x faster, but may not be accurate
0205 %     c = CC(iCCs(it),:); %colormap([1:64](it),:) %ie "This RGB color row ="
0206 %     si = iData(it)+1;   %[1:size(data)](it)+1;  %ie "This start row"
0207 %     ei = iData(it+1);   %[1:size(data)](it+1);  %ie "This end row"
0208 %     hh=quiver(xyuvvrNNs(si:ei,1),xyuvvrNNs(si:ei,2),...
0209 %               xyuvvrNNs(si:ei,3),xyuvvrNNs(si:ei,4),scale*it/n,'Color',c)
0210     cm_index = floor( (xyuvvrNNs(it,5) - colormin) / ( cm_stepsize ) ) + 1;
0211     if cm_index == 1             %in case colormin is zero
0212         c = CC(cm_index,:);
0213     elseif cm_index > length(CC) %in case max(xyuvvrNNs) > colormax
0214         cm_index = length(CC);
0215         c = CC(cm_index,:);
0216     elseif cm_index <= 0         %in case min(xyuvvrNNs) < colormin
0217         cm_index = 1;
0218         c = CC(cm_index,:);
0219     else
0220         cm_index = cm_index-1;
0221         c = CC(cm_index,:);
0222     end
0223     hh=quiver(xyuvvrNNs(it,1),xyuvvrNNs(it,2),...
0224               xyuvvrNNs(it,3),xyuvvrNNs(it,4),scale,'Color',c);
0225 end
0226 
0227 
0228 %----------Rest of document is from quiverc2wcmap---------------
0229 % This is Matlab's 6.5.1 quiver.  I figure that ensures a fair amouint of backward
0230 % compatibility but I needed to hack it to allow a 'Color' property.  Obviously
0231 % a person could do more.
0232     
0233 function hh = quiver(varargin)
0234 %QUIVER Quiver plot.
0235 %   QUIVER(X,Y,U,V) plots velocity vectors as arrows with components (u,v)
0236 %   at the points (x,y).  The matrices X,Y,U,V must all be the same size
0237 %   and contain corresponding position and velocity components (X and Y
0238 %   can also be vectors to specify a uniform grid).  QUIVER automatically
0239 %   scales the arrows to fit within the grid.
0240 %
0241 %   QUIVER(U,V) plots velocity vectors at equally spaced points in
0242 %   the x-y plane.
0243 %
0244 %   QUIVER(U,V,S) or QUIVER(X,Y,U,V,S) automatically scales the
0245 %   arrows to fit within the grid and then stretches them by S.  Use
0246 %   S=0 to plot the arrows without the automatic scaling.
0247 %
0248 %   QUIVER(...,LINESPEC) uses the plot linestyle specified for
0249 %   the velocity vectors.  Any marker in LINESPEC is drawn at the base
0250 %   instead of an arrow on the tip.  Use a marker of '.' to specify
0251 %   no marker at all.  See PLOT for other possibilities.
0252 %
0253 %   QUIVER(...,'filled') fills any markers specified.
0254 %
0255 %   H = QUIVER(...) returns a vector of line handles.
0256 %
0257 %   Example:
0258 %      [x,y] = meshgrid(-2:.2:2,-1:.15:1);
0259 %      z = x .* exp(-x.^2 - y.^2); [px,py] = gradient(z,.2,.15);
0260 %      contour(x,y,z), hold on
0261 %      quiver(x,y,px,py), hold off, axis image
0262 %
0263 %   See also FEATHER, QUIVER3, PLOT.
0264 
0265 %   Clay M. Thompson 3-3-94
0266 %   Copyright 1984-2002 The MathWorks, Inc.
0267 %   $Revision: 5.21 $  $Date: 2002/06/05 20:05:16 $
0268 
0269 % Arrow head parameters
0270 alpha = 0.33; % Size of arrow head relative to the length of the vector
0271 beta = 0.33;  % Width of the base of the arrow head relative to the length
0272 autoscale = 1; % Autoscale if ~= 0 then scale by this.
0273 plotarrows = 1; % Plot arrows
0274 sym = '';
0275 
0276 filled = 0;
0277 ls = '-';
0278 ms = '';
0279 col = 'b';
0280 
0281 nin = nargin;
0282 ColorSpecInd = find(strcmpi(varargin, 'color'));
0283 if(length(ColorSpecInd)==1 & nin > ColorSpecInd)
0284     col = varargin{ColorSpecInd+1};
0285     varargin = varargin([1:ColorSpecInd-1,ColorSpecInd+2:nin]);
0286     nin = nin-2;
0287 end
0288 % Parse the string inputs
0289 while isstr(varargin{nin}),
0290   vv = varargin{nin};
0291   if ~isempty(vv) & strcmp(lower(vv(1)),'f')
0292     filled = 1;
0293     nin = nin-1;
0294   else
0295     [l,c,m,msg] = colstyle(vv);
0296     if ~isempty(msg), 
0297       error(sprintf('Unknown option "%s".',vv));
0298     end
0299     if ~isempty(l), ls = l; end
0300     if ~isempty(c), col = c; end
0301     if ~isempty(m), ms = m; plotarrows = 0; end
0302     if isequal(m,'.'), ms = ''; end % Don't plot '.'
0303     nin = nin-1;
0304   end
0305 end
0306 
0307 error(nargchk(2,5,nin));
0308 
0309 % Check numeric input arguments
0310 if nin<4, % quiver(u,v) or quiver(u,v,s)
0311   [msg,x,y,u,v] = xyzchk(varargin{1:2});
0312 else
0313   [msg,x,y,u,v] = xyzchk(varargin{1:4});
0314 end
0315 if ~isempty(msg), error(msg); end
0316 
0317 if nin==3 | nin==5, % quiver(u,v,s) or quiver(x,y,u,v,s)
0318   autoscale = varargin{nin};
0319 end
0320 
0321 % Scalar expand u,v
0322 if prod(size(u))==1, u = u(ones(size(x))); end
0323 if prod(size(v))==1, v = v(ones(size(u))); end
0324 
0325 if autoscale,
0326   % Base autoscale value on average spacing in the x and y
0327   % directions.  Estimate number of points in each direction as
0328   % either the size of the input arrays or the effective square
0329   % spacing if x and y are vectors.
0330   if min(size(x))==1, n=sqrt(prod(size(x))); m=n; else [m,n]=size(x); end
0331   delx = diff([min(x(:)) max(x(:))])/n;
0332   dely = diff([min(y(:)) max(y(:))])/m;
0333   del = delx.^2 + dely.^2;
0334   if del>0
0335     len = sqrt((u.^2 + v.^2)/del);
0336     maxlen = max(len(:));
0337   else
0338     maxlen = 0;
0339   end
0340   
0341   if maxlen>0
0342     autoscale = autoscale*0.9 / maxlen;
0343   else
0344     autoscale = autoscale*0.9;
0345   end
0346   u = u*autoscale; v = v*autoscale;
0347 end
0348 
0349 ax = newplot;
0350 next = lower(get(ax,'NextPlot'));
0351 hold_state = ishold;
0352 
0353 % Make velocity vectors
0354 x = x(:).'; y = y(:).';
0355 u = u(:).'; v = v(:).';
0356 uu = [x;x+u;repmat(NaN,size(u))];
0357 vv = [y;y+v;repmat(NaN,size(v))];
0358 
0359 % h1 = plot(uu(:),vv(:),[col ls]);
0360 h1 = plot(uu(:),vv(:),ls,'Color',col);
0361 
0362 if plotarrows,
0363   % Make arrow heads and plot them
0364   hu = [x+u-alpha*(u+beta*(v+eps));x+u; ...
0365         x+u-alpha*(u-beta*(v+eps));repmat(NaN,size(u))];
0366   hv = [y+v-alpha*(v-beta*(u+eps));y+v; ...
0367         y+v-alpha*(v+beta*(u+eps));repmat(NaN,size(v))];
0368   hold on
0369  %  h2 = plot(hu(:),hv(:),[col ls]);
0370   h2 = plot(hu(:),hv(:),ls,'Color',col);
0371 else
0372   h2 = [];
0373 end
0374 
0375 if ~isempty(ms), % Plot marker on base
0376   hu = x; hv = y;
0377   hold on
0378 %  h3 = plot(hu(:),hv(:),[col ms]);
0379   h3 = plot(hu(:),hv(:),ls,'Color',col);
0380   if filled, set(h3,'markerfacecolor',get(h1,'color')); end
0381 else
0382   h3 = [];
0383 end
0384 
0385 if ~hold_state, hold off, view(2); set(ax,'NextPlot',next); end
0386 
0387 if nargout>0, hh = [h1;h2;h3]; end
0388 
0389     
0390 
0391 function retval = isscalar(m)
0392 retval = prod(size(m)) == 1;

Generated on Wed 20-Feb-2019 16:06:01 by m2html © 2005