Plotting a 3D graph of normalized prices in MatLab - matlab

I'm doing Gaussian processes and I calculated a regression per year from a given matrix where each row represents a year , so the code is:
M1 = MainMatrix; %This is the given Matrix
ker =#(x,y) exp(-1013*(x-y)'*(x-y));
[ns, ms] = size(M1);
for N = 1:ns
x = M1(N,:);
C = zeros(ms,ms);
for i = 1:ms
for j = 1:ms
C(i,j)= ker(x(i),x(j));
end
end
u = randn(ms,1);
[A,S, B] = svd(C);
z = A*sqrt(S)*u; % z = A S^.5 u
And I wanna plotting each regression in a Graph 3D as the below:
I know that plot is a ribbon, but I have not idea how can I do that

The desired plot can be generated without the use of ribbon. Just use a surf-plot for all the prices and a fill3-plot for the plane at z=0. The boundaries of the plane are calculated from the actual limits of the figure. Therefore we need to set the limits before plotting the plane. Then just some adjustments are needed to generate almost the same appearance.
Here is the code:
% generate some data
days = (1:100)';
price = days*[0.18,-0.08,0.07,-0.10,0.12,-0.08,0.05];
price = price + 0.5*randn(size(price));
years = 2002+(1:size(price,2));
% prepare plot
width = 0.6;
X = ones(size(price,1),1)*0.5;
X = [-X,X]*width;
figure; hold on;
% plot all 'ribbons'
for i = 1:size(price,2)
h = surf([days,days],X+years(i),[price(:,i),price(:,i)]);
set(h,'MeshStyle','column');
end
% set axis limits
set(gca,'ZLim',[-20,20]);
% plot plane at z=0
limx = get(gca,'XLim');
limy = get(gca,'YLim');
fill3(reshape([limx;limx],1,[]),[flip(limy),limy],zeros(1,4),'g','FaceAlpha',0.2)
% set labels
xlabel('Day of trading')
ylabel('Year')
zlabel('Normalized Price')
% tweak appearance
set(gca,'YTick',years);
set(gca,'YDir','reverse');
view([-38,50])
colormap jet;
grid on;
%box on;
This is the result:

That's a ribbon plot with an additional surface at y=0 which can be drawn with fill3

Related

Producing a histogram in Matlab with out using Hist

I am using histograms in Matlab to look at the distribution of some data from my experiments. I want to find the mean distribution (mean height of the bars) from a group of tests then produce an average histogram.
By using this code:
data = zeros(26,31);
for i = 1:length(files6)
x = csvread(files6(i).name);
x = x(1:end,:);
time = x(:,1);
variable = x(:,3);
thing(:,1) = x(:,1);
thing(:,2) = x(:,3);
figure()
binCenter = {0:tbinstep:tbinend 0:varbinstep:varbinend};
hist3(thing, 'Ctrs', binCenter, 'CDataMode','auto','FaceColor','interp');
colorbar
[N,C] = hist3(thing, 'Ctrs', binCenter);
data = data + N;
clearvars x time variable
end
avedata = data / i;
I can find the mean of N, which will be the Z value for the plot (histogram) I want, and I have X,Y (which are the same for all tests) from:
x = 0:tbinstep:tbinend;
y = 0:varbinstep:varbinend;
But how do I bring these together to make the graphical out that shows the average height of the bars? I can't use hist3 again as that will just calculate the distribution of avedata.
AT THE RISK OF STARTING AN XY PROBLEM using bar3 has been suggested, but that asks the question "how do I go from 2 vectors and a matrix to 1 matrix bar3 can handle? I.e. how do I plot x(1), y(1), avedata(1,1) and so on for all the data points in avedata?"
TIA
By looking at hist3 source code in matlab r2014b, it has his own plotting implemented inside that prepares data and plot it using surf method. Here is a function that reproduce the same output highly inspired from the hist3 function with your options ('CDataMode','auto','FaceColor','interp'). You can put this in a new file called hist3plot.m:
function [ h ] = hist3plot( N, C )
%HIST3PLOT Summary of this function goes here
% Detailed explanation goes here
xBins = C{1};
yBins = C{2};
% Computing edges and width
nbins = [length(xBins), length(yBins)];
xEdges = [0.5*(3*xBins(1)-xBins(2)), 0.5*(xBins(2:end)+xBins(1:end-1)), 0.5*(3*xBins(end)-xBins(end-1))];
yEdges = [0.5*(3*yBins(1)-yBins(2)), 0.5*(yBins(2:end)+yBins(1:end-1)), 0.5*(3*yBins(end)-yBins(end-1))];
xWidth = xEdges(2:end)-xEdges(1:end-1);
yWidth = yEdges(2:end)-yEdges(1:end-1);
del = .001; % space between bars, relative to bar size
% Build x-coords for the eight corners of each bar.
xx = xEdges;
xx = [xx(1:nbins(1))+del*xWidth; xx(2:nbins(1)+1)-del*xWidth];
xx = [reshape(repmat(xx(:)',2,1),4,nbins(1)); NaN(1,nbins(1))];
xx = [repmat(xx(:),1,4) NaN(5*nbins(1),1)];
xx = repmat(xx,1,nbins(2));
% Build y-coords for the eight corners of each bar.
yy = yEdges;
yy = [yy(1:nbins(2))+del*yWidth; yy(2:nbins(2)+1)-del*yWidth];
yy = [reshape(repmat(yy(:)',2,1),4,nbins(2)); NaN(1,nbins(2))];
yy = [repmat(yy(:),1,4) NaN(5*nbins(2),1)];
yy = repmat(yy',nbins(1),1);
% Build z-coords for the eight corners of each bar.
zz = zeros(5*nbins(1), 5*nbins(2));
zz(5*(1:nbins(1))-3, 5*(1:nbins(2))-3) = N;
zz(5*(1:nbins(1))-3, 5*(1:nbins(2))-2) = N;
zz(5*(1:nbins(1))-2, 5*(1:nbins(2))-3) = N;
zz(5*(1:nbins(1))-2, 5*(1:nbins(2))-2) = N;
% Plot the bars in a light steel blue.
cc = repmat(cat(3,.75,.85,.95), [size(zz) 1]);
% Plot the surface
h = surf(xx, yy, zz, cc, 'CDataMode','auto','FaceColor','interp');
% Setting x-axis and y-axis limits
xlim([yBins(1)-yWidth(1) yBins(end)+yWidth(end)]) % x-axis limit
ylim([xBins(1)-xWidth(1) xBins(end)+xWidth(end)]) % y-axis limit
end
You can then call this function when you want to plot outputs from Matlab's hist3 function. Note that this can handle non uniform positionning of bins:
close all; clear all;
data = rand(10000,2);
xBins = [0,0.1,0.3,0.5,0.6,0.8,1];
yBins = [0,0.1,0.3,0.5,0.6,0.8,1];
figure()
hist3(data, {xBins yBins}, 'CDataMode','auto','FaceColor','interp')
title('Using hist3')
figure()
[N,C] = hist3(data, {xBins yBins});
hist3plot(N, C); % The function is called here
title('Using hist3plot')
Here is a comparison of the two outputs:
So if I understand your question and code correctly, you are plotting the distribution of multiple experiments' data as histograms, then you want to calculate the average shape of all the previous histograms.
I usually avoid giving approaches the asker isn't explicitly asking for, but for this one I must comment that it is a very strange thing to do. I've never heard of calculating the average shape of multiple histograms before. So just in case, you could simply append all your experiment's data into a single variable, and plot a normalized histogram of that using histogram2. This code outputs a relative frequency histogram. (Other normalization methods)
% Append all data in a single matrix
x = []
for i = 1:length(files6)
x = [x; csvread(files6(i).name)];
end
% Plot normalized bivariate histogram, normalized
xEdges = 0:tbinstep:tbinend;
yEdges = 0:varbinstep:varbinend;
histogram2(x(:,1), x(:,3), xEdges, yEdges, 'Normalize', 'Probability')
Now, if you really are looking to draw the average shape of multiple histograms, then yes, use bar3. Since bar3 doesn't accept an (x,y) value argument, you can follow the other answer, or modify the XTickLabel and YTickLabel property to match whatever your bin range is, afterwards.
... % data = yourAverageData;
% Save axis handle to `h`
h = bar3(data);
% Set property of axis
h.XTickLabels = 0:tbinstep:tbinend;
h.YTickLabels = 0:varbinstep:varbinend;

build my own function that does the same work as 'semilogx' MATLAB function

How can I build my own function in Matlab that does the same work as the Matlab built-in function 'semilogx'?
Example: in this example both fig.1 and fig.2 plot x as a log scale but the values on the x-axis of fig.1 are not correct. So the question is "how can I make the values in fig.1 same as the values in fig.2 without using semilogx?"
x = 0:1000;
y = 2*x;
figure(1), plot(log10(x), y)
figure(2), semilogx(x,y)
I guess in my example above: in Fig.1 x limit is between [0,3] and in Fig.2 x limit is between [0,1000]. What I understand is that x limit should be [0:1000] but when we use log scale this would change to [0,3] so the semilogx function only maps the [0,3] limit to [0,1000]
Basically you have to reconstruct the x-axis tick mark locations and the corresponding tick labels on a log-scaled grid:
% Some data
x = 1:1000;
y = cumsum(rand(size(x)));
% For comparison
subplot(311); plot(log10(x), y)
subplot(312); semilogx(x,y)
% Simulated semilogx plot
subplot(313); plot(log10(x), y)
ax = gca; % Get a handle to the axis for tick modifications
% Compute tick mark locations in log10 scale
logxmax = ceil(log10(x(end)));
ticks = log10(1:9);
ticks = ticks' + (0:logxmax-1);
ticks = [ticks(:); logxmax];
% Set tick marks and labels
ax.XTick = ticks;
ax.XLim = [0 logxmax];
% Reset tick labels
ax.XTickLabel(:) = ''; % clear all tick labels
I = 1+9*(0:logxmax); % Tick labels for 10^n locations
S = arrayfun(#(x)'10^{'+string(x)+'}', (0:logxmax), 'UniformOutput', false);
ax.XTickLabel(I) = S;

Matlab: patch area between two curves which depend on the curves values

I'm trying to fill an area between two curves with respect to a function which depends on the values of the curves.
Here is the code of what I've managed to do so far
i=50;
cc = #(xx,x,y) 1./(1+(exp(-xx)/(exp(-x)-exp(-y))));
n_vec = 2:0.1:10;
x_vec = linspace(2,10,length(n_vec));
y_vec = abs(sin(n_vec));
N=[n_vec,fliplr(n_vec)];
X=[x_vec,fliplr(y_vec)];
figure(1)
subplot(2,1,1)
hold on
plot(n_vec,x_vec,n_vec,y_vec)
hp = patch(N,X,'b')
plot([n_vec(i) n_vec(i)],[x_vec(i),y_vec(i)],'linewidth',5)
xlabel('n'); ylabel('x')
subplot(2,1,2)
xx = linspace(y_vec(i),x_vec(i),100);
plot(xx,cc(xx,y_vec(i),x_vec(i)))
xlabel('x'); ylabel('c(x)')
This code produces the following graph
The color code which I've added represent the color coding that each line (along the y axis at a point on the x axis) from the area between the two curves should be.
Overall, the entire area should be filled with a gradient color which depends on the values of the curves.
I've assisted the following previous questions but could not resolve a solution
MATLAB fill area between lines
Patch circle by a color gradient
Filling between two curves, according to a colormap given by a function MATLAB
NOTE: there is no importance to the functional form of the curves, I would prefer an answer which refers to two general arrays which consist the curves.
The surf plot method
The same as the scatter plot method, i.e. generate a point grid.
y = [x_vec(:); y_vec(:)];
resolution = [500,500];
px = linspace(min(n_vec), max(n_vec), resolution(1));
py = linspace(min(y), max(y), resolution(2));
[px, py] = meshgrid(px, py);
Generate a logical array indicating whether the points are inside the polygon, but no need to extract the points:
in = inpolygon(px, py, N, X);
Generate Z. The value of Z indicates the color to use for the surface plot. Hence, it is generated using the your function cc.
pz = 1./(1+(exp(-py_)/(exp(-y_vec(i))-exp(-x_vec(i)))));
pz = repmat(pz',1,resolution(2));
Set Z values for points outside the area of interest to NaN so MATLAB won't plot them.
pz(~in) = nan;
Generate a bounded colourmap (delete if you want to use full colour range)
% generate colormap
c = jet(100);
[s,l] = bounds(pz,'all');
s = round(s*100);
l = round(l*100);
if s ~= 0
c(1:s,:) = [];
end
if l ~= 100
c(l:100,:) = [];
end
Finally, plot.
figure;
colormap(jet)
surf(px,py,pz,'edgecolor','none');
view(2) % x-y view
Feel free to turn the image arround to see how it looks like in the Z-dimention - beautiful :)
Full code to test:
i=50;
cc = #(xx,x,y) 1./(1+(exp(-xx)/(exp(-x)-exp(-y))));
n_vec = 2:0.1:10;
x_vec = linspace(2,10,length(n_vec));
y_vec = abs(sin(n_vec));
% generate grid
y = [x_vec(:); y_vec(:)];
resolution = [500,500];
px_ = linspace(min(n_vec), max(n_vec), resolution(1));
py_ = linspace(min(y), max(y), resolution(2));
[px, py] = meshgrid(px_, py_);
% extract points
in = inpolygon(px, py, N, X);
% generate z
pz = 1./(1+(exp(-py_)/(exp(-y_vec(i))-exp(-x_vec(i)))));
pz = repmat(pz',1,resolution(2));
pz(~in) = nan;
% generate colormap
c = jet(100);
[s,l] = bounds(pz,'all');
s = round(s*100);
l = round(l*100);
if s ~= 0
c(1:s,:) = [];
end
if l ~= 100
c(l:100,:) = [];
end
% plot
figure;
colormap(c)
surf(px,py,pz,'edgecolor','none');
view(2)
You can use imagesc and meshgrids. See comments in the code to understand what's going on.
Downsample your data
% your initial upper and lower boundaries
n_vec_long = linspace(2,10,1000000);
f_ub_vec_long = linspace(2, 10, length(n_vec_long));
f_lb_vec_long = abs(sin(n_vec_long));
% downsample
n_vec = linspace(n_vec_long(1), n_vec_long(end), 1000); % for example, only 1000 points
% get upper and lower boundary values for n_vec
f_ub_vec = interp1(n_vec_long, f_ub_vec_long, n_vec);
f_lb_vec = interp1(n_vec_long, f_lb_vec_long, n_vec);
% x_vec for the color function
x_vec = 0:0.01:10;
Plot the data
% create a 2D matrix with N and X position
[N, X] = meshgrid(n_vec, x_vec);
% evaluate the upper and lower boundary functions at n_vec
% can be any function at n you want (not tested for crossing boundaries though...)
f_ub_vec = linspace(2, 10, length(n_vec));
f_lb_vec = abs(sin(n_vec));
% make these row vectors into matrices, to create a boolean mask
F_UB = repmat(f_ub_vec, [size(N, 1) 1]);
F_LB = repmat(f_lb_vec, [size(N, 1) 1]);
% create a mask based on the upper and lower boundary functions
mask = true(size(N));
mask(X > F_UB | X < F_LB) = false;
% create data matrix
Z = NaN(size(N));
% create function that evaluates the color profile for each defined value
% in the vectors with the lower and upper bounds
zc = #(X, ub, lb) 1 ./ (1 + (exp(-X) ./ (exp(-ub) - exp(-lb))));
CData = zc(X, f_lb_vec, f_ub_vec); % create the c(x) at all X
% put the CData in Z, but only between the lower and upper bound.
Z(mask) = CData(mask);
% normalize Z along 1st dim
Z = normalize(Z, 1, 'range'); % get all values between 0 and 1 for colorbar
% draw a figure!
figure(1); clf;
ax = axes; % create some axes
sc = imagesc(ax, n_vec, x_vec, Z); % plot the data
ax.YDir = 'normal' % set the YDir to normal again, imagesc reverses it by default;
xlabel('n')
ylabel('x')
This already looks kinda like what you want, but let's get rid of the blue area outside the boundaries. This can be done by creating an 'alpha mask', i.e. set the alpha value for all pixels outside the previously defined mask to 0:
figure(2); clf;
ax = axes; % create some axes
hold on;
sc = imagesc(ax, n_vec, x_vec, Z); % plot the data
ax.YDir = 'normal' % set the YDir to normal again, imagesc reverses it by default;
% set a colormap
colormap(flip(hsv(100)))
% set alpha for points outside mask
Calpha = ones(size(N));
Calpha(~mask) = 0;
sc.AlphaData = Calpha;
% plot the other lines
plot(n_vec, f_ub_vec, 'k', n_vec, f_lb_vec, 'k' ,'linewidth', 1)
% set axis limits
xlim([min(n_vec), max(n_vec)])
ylim([min(x_vec), max(x_vec)])
there is no importance to the functional form of the curves, I would prefer an answer which refers to two general arrays which consist the curves.
It is difficult to achieve this using patch.
However, you may use scatter plots to "fill" the area with coloured dots. Alternatively, and probably better, use surf plot and generate z coordinates using your cc function (See my seperate solution).
The scatter plot method
First, make a grid of points (resolution 500*500) inside the rectangular space bounding the two curves.
y = [x_vec(:); y_vec(:)];
resolution = [500,500];
px = linspace(min(n_vec), max(n_vec), resolution(1));
py = linspace(min(y), max(y), resolution(2));
[px, py] = meshgrid(px, py);
figure;
scatter(px(:), py(:), 1, 'r');
The not-interesting figure of the point grid:
Next, extract the points inside the polygon defined by the two curves.
in = inpolygon(px, py, N, X);
px = px(in);
py = py(in);
hold on;
scatter(px, py, 1, 'k');
Black points are inside the area:
Finally, create color and plot the nice looking gradient colour figure.
% create color for the points
cid = 1./(1+(exp(-py)/(exp(-y_vec(i))-exp(-x_vec(i)))));
c = jet(101);
c = c(round(cid*100)+1,:); % +1 to avoid zero indexing
% plot
figure;
scatter(px,py,16,c,'filled','s'); % use size 16, filled square markers.
Note that you may need a fairly dense grid of points to make sure the white background won't show up. You may also change the point size to a bigger value (won't impact performance).
Of cause, you may use patch to replace scatter but you will need to work out the vertices and face ids, then you may patch each faces separately with patch('Faces',F,'Vertices',V). Using patch this way may impact performance.
Complete code to test:
i=50;
cc = #(xx,x,y) 1./(1+(exp(-xx)/(exp(-x)-exp(-y))));
n_vec = 2:0.1:10;
x_vec = linspace(2,10,length(n_vec));
y_vec = abs(sin(n_vec));
% generate point grid
y = [x_vec(:); y_vec(:)];
resolution = [500,500];
px_ = linspace(min(n_vec), max(n_vec), resolution(1));
py_ = linspace(min(y), max(y), resolution(2));
[px, py] = meshgrid(px_, py_);
% extract points
in = inpolygon(px, py, N, X);
px = px(in);
py = py(in);
% generate color
cid = 1./(1+(exp(-py)/(exp(-y_vec(i))-exp(-x_vec(i)))));
c = jet(101);
c = c(round(cid*100)+1,:); % +1 to avoid zero indexing
% plot
figure;
scatter(px,py,16,c,'filled','s');

Two plots of same wave in MatLab, but plot created after transforming to polar coordinates is distorded?

I have created some MatLab code that plots a plane wave using two different expressions that give the same plane wave. The first expression is in Cartesian coordinates and works fine. However, the second expression is in polar coordinates and when I calculate the plane wave in this case, the plot is distorted. Both plots should look the same. So what am I doing wrong in transforming to/from polar coordinates?
function Plot_Plane_wave()
clc
clear all
close all
%% Step 0. Input paramaters and derived parameters.
alpha = 0*pi/4; % angle of incidence
k = 1; % wavenumber
wavelength = 2*pi/k; % wavelength
%% Step 1. Define various equivalent versions of the incident wave.
f_u_inc_1 = #(alpha,x,y) exp(1i*k*(x*cos(alpha)+y*sin(alpha)));
f_u_inc_2 = #(alpha,r,theta) exp(1i*k*r*cos(theta-alpha));
%% Step 2. Evaluate the incident wave on a grid.
% Grid for field
gridMax = 10;
gridN = 2^3;
g1 = linspace(-gridMax, gridMax, gridN);
g2 = g1;
[x,y] = meshgrid(g1, g2);
[theta,r] = cart2pol(x,y);
u_inc_1 = f_u_inc_1(alpha,x,y);
u_inc_2 = 0*x;
for ir=1:gridN
rVal = r(ir);
for itheta=1:gridN
thetaVal = theta(itheta);
u_inc_2(ir,itheta) = f_u_inc_2(alpha,rVal,thetaVal);
end
end
%% Step 3. Plot the incident wave.
figure(1);
subplot(2,2,1)
imagesc(g1(1,:), g1(1,:), real(u_inc_1));
hGCA = gca; set(hGCA, 'YDir', 'normal');
subplot(2,2,2)
imagesc(g1(1,:), g1(1,:), real(u_inc_2));
hGCA = gca; set(hGCA, 'YDir', 'normal');
end
Your mistake is that your loop is only going through the first gridN values of r and theta. Instead you want to step through the indices of ix and iy and pull out the rVal and thetaVal of the matrices r and theta.
You can change your loop to
for ix=1:gridN
for iy=1:gridN
rVal = r(ix,iy); % Was equivalent to r(ix) outside inner loop
thetaVal = theta(ix,iy); % Was equivalent to theta(iy)
u_inc_2(ix,iy) = f_u_inc_2(alpha,rVal,thetaVal);
end
end
which gives the expected graphs.
Alternatively you can simplify your code by feeding matrices in to your inline functions. To do this you would have to use an elementwise product .* instead of a matrix multiplication * in f_u_inc_2:
alpha = 0*pi/4;
k = 1;
wavelength = 2*pi/k;
f_1 = #(alpha,x,y) exp(1i*k*(x*cos(alpha)+y*sin(alpha)));
f_2 = #(alpha,r,theta) exp(1i*k*r.*cos(theta-alpha));
% Change v
f_old = #(alpha,r,theta) exp(1i*k*r *cos(theta-alpha));
gridMax = 10;
gridN = 2^3;
[x,y] = meshgrid(linspace(-gridMax, gridMax, gridN));
[theta,r] = cart2pol(x,y);
subplot(1,3,1)
contourf(x,y,real(f_1(alpha,x,y)));
title 'Cartesian'
subplot(1,3,2)
contourf(x,y,real(f_2(alpha,r,theta)));
title 'Polar'
subplot(1,3,3)
contourf(x,y,real(f_old(alpha,r,theta)));
title 'Wrong'

Specifying quiver vector color by density

I have some vectors with defined position and orientation. I could show them in space by using the below code:
theta = [pi/2,-pi/2,pi/2,pi/2,pi/2,pi/2,pi/2];
r = 0.25; % magnitude (length) of arrow to plot
x = [4,3.5,3.75,4.5,8,10,12]; y = [8.5,8.2,8.3,8,9,10,8];
u = r * cos(theta); % convert polar (theta,r) to cartesian
v = r * sin(theta);
h = quiver(x,y,u,v,'linewidth',2);
set(gca, 'XLim', [2 15], 'YLim', [4 15]);
As is clear from the image, in some regions the number of arrows is more than in other places. I want to show the arrows by color, where each color represents the density of the arrows.
Could anyone help me to do that? It would also be a good solution if there is a continuous background color which shows local densities.
Edit: Below are some options for colouring the background of the plot depending on the density of your points. I'm editing this into the top of my answer because it actually answers your question - individually colouring quiver arrows based on density!
x = rand(200,1)*10; y = rand(200,1)*10; % Set up random points
r = 1; u = r * cos(x); v = r * sin(y); % Quiver directions
colormap winter; c = colormap; % Set colourmap and assign to matrix
% Get density of points broken into a 10x10 grid
[n,~,~,binX,binY] = histcounts2(x,y,[10,10]);
% Get colour based on histogram density and chosen colormap colours
col = c(ceil(n(sub2ind(size(n), binX, binY))/max(n(:))*size(c,1)),:);
figure; hold on;
% Each quiver point must be plotted individually (slow!) because colours can
% only be applied to individual quivers. This could be sped up by plotting
% all of the same colour at once.
for ii = 1:size(x,1);
quiver(x(ii),y(ii),u(ii),v(ii),0,'color',col(ii,:));
end
Output:
Note: unlike the below example, you cannot use hist3 because you need it to return the bin index too. You could try this File Exchange function to achieve the same result (untested).
Here is an option using hist3 to get the density (in this example I use a 10x10 grid, as specified when calling hist3). Then using pcolor to display the density, and shading interp to smooth the colours.
Note: hist3 requires the Stats & ML toolbox, if you have Matlab 2015b or newer you can instead use the standard function histcounts2(x,y).
% Generate points and quiver directions
x = rand(200,1)*10; y = rand(200,1)*10;
u = r * cos(x); v = r * sin(y);
% Get density of points, format for input to pcolor
n = hist3([x,y],[10,10]); % Get density of points broken into a 10x10 grid
colx = linspace(min(x),max(x),size(n,1)+1);
coly = linspace(min(y),max(y),size(n,1)+1);
n = n'; n(size(n,2)+1,size(n,1)+1) = 0;
% Plot
figure
pcolor(colx,coly,n) % Density plot
hold on; colorbar; % Hold on for next plot and show colour bar key
quiver(x,y,u,v,'r') % Quiver plot
shading interp % Smooth plot colours
Output:
Edit: making the colours more muted
You can control the colours using colormap. This could be one of the defaults, or you can create a custom map of RGB triplets and have whatever colours you want! Here is an example, simply calling colormap bone; at the end of the above code:
In a custom colour map, you could make the colours even more muted / less contrasting.
Additionally, you can use caxis to scale the colour axis of a plot! Simply call
caxis([0,2*max(n(:))]);
at the end of the above code to double the maximum colour map value. You can tweak the 2 to get desired results:
this looks way less fancy but specifies the arrow color as function of the number of arrows in a certain number of bins of the x-axis
close all;
cm=colormap;
theta = [pi/2,-pi/2,pi/2,pi/2,pi/2,pi/2,pi/2];
r = 0.25; % magnitude (length) of arrow to plot
x = [4,3.5,3.75,4.5,8,10,12]; y = [8.5,8.2,8.3,8,9,10,8];
[n,c]=hist(x,5); %count arroes in bins
u = r * cos(theta); % convert polar (theta,r) to cartesian
v = r * sin(theta);
figure;hold on
for ii=1:numel(n) %quiver bin by bin
if n(ii)>0
if ii==1
wx=find(x<(c(ii)+(c(ii+1) - c(ii))/2)); %Which X to plot
elseif ii==numel(n)
wx=find(x>c(numel(n)-1));
else
wx=find((x>(c(ii)-(c(ii)-c(ii-1))/2)).*(x<(c(ii+1)-(c(ii+1)-c(ii))/2)));
end
indCol=ceil( (size(cm,1)*n(ii)-0) / max(n));%color propto density of arrows %in this bin
col = cm(indCol,:);%color for this bin
h = quiver(x(wx),y(wx),u(wx),v(wx),0,'linewidth',2,'color',col);
end
end
colorbar
caxis([0 max(n)])