Matlab: `mesh()` plot with less number of grid - matlab

Let's say data is a matrix of size 129 * 129.
by using
mesh(data, 'FaceColor', 'none', 'EdgeColor', 'black')
we get something like
We can find that the grid are quite intense. I would like to have the same figure but with less number of mesh lines, something like
It is of course doable to plot a smaller data, for example data(1:10:end, 1:10:end). But in this way, the plot are not accurate as before anymore.
Another example is plot(..., 'MarkerIndices', ...). This can give you a plot with less number of markers without modifying the plot. https://www.mathworks.com/help/matlab/creating_plots/create-line-plot-with-markers.html

An alternative approach is to use plot3 to plot the mesh lines manually. That way you can plot each line smoothly using all the data points, but not have as many lines.
[X,Y,Z] = peaks(201);
step = 5;
plot3(X(:,1:step:end),Y(:,1:step:end),Z(:,1:step:end),'k')
hold on
plot3(X(1:step:end,:).',Y(1:step:end,:).',Z(1:step:end,:).','k')
hold off

I think your best option would be to create a surf plot with no grid lines (showing a colored surface with the full resolution of your data), then overlay a down-sampled mesh plot. Something like this:
surf(data, 'EdgeColor', 'none');
hold on;
mesh(data(1:10:end, 1:10:end), 'EdgeColor', 'black');
You could also add some transparency to the surf plot to make the mesh visible through it:
surf(data, 'FaceAlpha', 0.7, 'EdgeColor', 'none');

The answer from #David is good. In addition to his approach, we can also replace plot3 with many infinitesimal mesh. The idea is to plot mesh for single vectors many times.
[X,Y,Z] = peaks(201);
tempz = NaN(201, 201);
tempz(1, :) = Z(1, :);
mesh(X, Y, tempz, 'EdgeColor', 'interp');
hold on
% plot x lines
for i = 2:10:201
tempz = NaN(201, 201);
tempz(i, :) = Z(i, :);
mesh(X, Y, tempz, 'EdgeColor', 'interp');
end
% plot y lines
for i = 2:10:201
tempz = NaN(201, 201);
tempz(:, i) = Z(:, i);
mesh(X, Y, tempz, 'EdgeColor', 'interp');
end
The original is
By using the snippet above, it gives
The benefits of this over #David's answer is that you can preserve all of the fancy properties of mesh, for example shading interp etc.

Related

How to plot unevenly spaced data on Matlab / Origin?

I want to plot my following data:
x-axis: [0,10,50,100,500,1000,1500]
y-axis: [75.6,78,78.2,81.8,84.7,85.2,86.3]
As seen above, the data on the x-axis are unevenly spaced. When I plot the above data linearly using origin, I get:
I got the similar graph on Matlab too. Notice that most of the Amp data lie for x<500. I want to plot the graph such that the whole output (y-axis) become clearly visible. For this, I tried using the Logarithmic plot. I changed the x-axis into logarithmic in Matlab as follows:
set(gca, 'XScale','log');
In Origin, we can use GUI to change the x-axis to logarithmic. The obtained graphs are as follows:
The obtained graphs are still not good. Any ideas, please!
Thank you very much.
https://www.mathworks.com/help/matlab/ref/semilogx.html
x = [0,10,50,100,500,1000,1500];
y = [75.6,78,78.2,81.8,84.7,85.2,86.3];
semilogx(x,y,'.-', 'markersize', 15);
set(gca,'XTick',x);
set(gca,'XTickLabelRotation',45);
x = [0,10,50,100,500,1000,1500];
y = [75.6,78,78.2,81.8,84.7,85.2,86.3];
y2 = [80,84,85,86,89,90,92];
semilogx(x+1,y,'.-', 'markersize', 15);
set(gca,'XTick',x);
set(gca,'XTickLabelRotation',45);
hold on;
semilogx(x+1,y2,'.-', 'markersize', 15);
hold off;
grid on;
legend('y1','y');

Add stippling to surface plot

I have a variable A the size 100x150 with temperature values that I've plotted using the surface command.
Now I'd like to plot another variable B (consisting of 1's and NaN's) over A such that the 1's are displayed as some sort of stippling (in black), while nothing happens for the NaN's.
The result should look something like this IPCC figure.
I was able to plot the stippling in B separately, by using Markers and setting the colormap to white:
figure
surface(longitude, latitude, B, 'edgecolor', 'none', 'marker', 'o');
colormap([1 1 1]);
but I don't know how to plot both A and B in one figure.
I've also tried other commands such as plot3 but I couldn't figure it out so far.
Any help, also just a hint as to which function to use, would be much appreciated!
You're going to want to create two surfaces, one with your image data and the other will be of the other black regions that you would like to display. To do this, you can either alter the AlphaData property of the overlay (shown below) or you can set the CData to NaN and those values should be see-through in the resulting image. I think that the AlphaData approach is more appropriate since you want the grid to be uniform regardless of the topology of the data.
I have included an example of the AlphaData approach below
load mri
im = double(squeeze(D(:,:,12)));
figure;
surface(im, 'EdgeColor', 'none');
axis image
% Create an overlay image that will display as black
[w,h] = size(im);
nWide = ceil(w / 10);
nHigh = ceil(h / 10);
checker = checkerboard(10, nWide, nHigh);
checker = checker(1:w, 1:h);
% Now plot the overlay
hold on
[xx,yy] = meshgrid(1:w, 1:h);
s = surface(xx, yy, ones(size(xx))*max(im(:)));
set(s, 'EdgeColor', 'none', ...
'FaceAlpha', 'flat', ...
'AlphaData', checker, ...
'FaceColor', 'black');
And here is the view from the side just so you can see how it was done.
Alternately, rather than using surface you could use pcolor for the overlay:
s = pcolor(checker);
set(s, 'EdgeColor', 'none', ...
'FaceAlpha', 'flat', ...
'AlphaData', checker, ...
'FaceColor', 'black)
% And set the ZData so it's above your data
set(s, 'ZData', ones(size(checker)) * max(im(:)))
The other nice thing about this approach is that it uses RGB for the color of the overlay so it's appearance is independent of the colormap used for the underlying data.

Visualize sparsity pattern with intensity using Matlab spy function

Matlab has a function spy for visualizing sparsity patterns of graph adjacency matrices.
Unfortunately it does not display the points by taking into account the magnitude of the values in the matrix. It uses a single color with same intensity to display all entries.
I wish to display the same spy plot but with the points "color-coded" like in a heatmap to indicate the magnitude of the entries. How can I do that?
spy function uses plot, which cannot have different marker colors in a lineseries object.
On the other hand, patch object can have different marker colors for different vertices. patch is originally for drawing polygons, but with no face color and no edge color, one can get similar result to plot with no line style.
S = bucky();
[m, n] = size(S);
[X, Y] = meshgrid(1:m, 1:n);
S = (X + Y) .* S;
nonzeroInd = find(S);
[x, y] = ind2sub([m n], nonzeroInd);
figure();
hp = patch(x, y, S(nonzeroInd), ...
'Marker', 's', 'MarkerFaceColor', 'flat', 'MarkerSize', 4, ...
'EdgeColor', 'none', 'FaceColor', 'none');
set(gca, 'XLim', [0, n + 1], 'YLim', [0, m + 1], 'YDir', 'reverse', ...
'PlotBoxAspectRatio', [n + 1, m + 1, 1]);
colorbar();
You can easily use different colormap, e.g., colormap(flipud(hot)).
If your matrix is not very large you could try to view it as an image using imagesc(). (Well you could use it for quite large matrices as well, but the pixels become very small.)
Here is an example of 20 random points in a 100x100 matrix, using colormap hot:
N = 100;
n = 20;
x = randi(N,1,n);
y = randi(N,1,n);
z = randi(N,1,n);
data = sparse(x,y,z);
imagesc(data)
axis square
colormap('hot')
This is the resulting image.
This can be compared to the plot we get using spy(data) where the markers are a bit larger.
If a white background is desired an easy way to achieve this is to flip the colormap:
figure
imagesc(data)
axis square
cmap = flipud(colormap('hot'));
colormap(cmap)
Hack solution redefining spy()
Googling a bit I found this thread at Matlab Central:
Spy with color for values?
There a solution is suggested that redefines spy(). It's however worth noting that (further down in the thread) this solution can also cause Matlab to crash for larger matrices.
I submitted a file on matlab exchange that also performs the spy task with points colored according to their value. Please see here.

Matlab: How to smooth colors of matrix in plot3( ) function?

I am using plot3 to plot a matrix such that the resultant figure shows different colors for each vector of that matrix:
plot3(Grid.x1(:,:),Grid.x2(:,:),phi(:,:))
How can I smooth the coloring of this plot? Thanks!
You can use varycolor from FileExchange to construct and control a continuous range color spectrum. This way the transition between different lines will seem more natural and proximal lines will have similar colors.
You can read more and see examples usage here http://blogs.mathworks.com/pick/2008/08/15/colors-for-your-multi-line-plots/
Example:
[X,Y,Z] = peaks(128);
% raw plot3()
figure; plot3(X, Y, Z);
% define set equal to line number
ColorSet = varycolor(128);
% smooth plot3()
figure; hold all;
set(gca, 'ColorOrder', ColorSet);
plot3(X, Y, Z); view(3);
Update:
For a continuous 3D plot (i.e. a surface) you can use surfl instead of plot3 and display your data as a 3-D Surface Plot (with Shading). You can additionally apply any colormap on the resulting surface, i.e. gray or ColorSet as above.
surfl(X,Y,Z);
shading interp;
colormap(gray);

Plotting a subplot on top of another plot in Matlab

I need to plot several plots along a sloped line at different positions.
For example, if I:
plot(0:200,'k');
plotpts = 5:5:200;
I would like to be able to plot a smaller plot at each of my plotpts on top of the original 0:200 line.
I know you can use hold on and plot over top that way, but I need to change my origin each time. Does anyone have any suggestions? I would really like to stay in matlab. Thanks!
Here is a flexible way I usually do it:
plot(1:10, 'k')
plotpts = 2:2:8;
mainbox = get(gca, 'Position');
xlims = get(gca, 'XLim');
ylims = get(gca, 'Ylim');
for i=1:length(plotpts)
originx = mainbox(1) + (plotpts(i) - xlims(1)) * (mainbox(3)) / (xlims(2) - xlims(1));
originy = mainbox(2) + (plotpts(i) - ylims(1)) * (mainbox(4)) / (ylims(2) - ylims(1));
axes('position', [originx originy 0.1 0.1], 'Color', 'none')
% Do some plotting here...
end
It's quite a bit of work, but you probably want to use the axes command. A figure window can host any number of axes, where each axes has it's own position, data, annotations, color etc.
The most difficult thing for the application you describe is that each axis position needs to be defined in the coordinate frame of the underlying figure, which means that some math may be required to create the illusion that the axis is correctly positioned within a parent axes/
For example, if you first create a simple plot
figure(1234); clf;
plot(1:10, rand(1,10),'.k-','linewidth',5);
xlim([1 10]);
ylim([0 1]);
set(gca,'color','y'); %This just helps demonstrate the next steps
You can place another axis directly on top of the first, and then
ha = axes('position',[.2 .3 .1 .1])
plot(linspace(0,2*pi,100), sin(linspace(0,2*pi,100)), 'b-')
xlim([0 2*pi])
You can adjust the the properties of the inset axis to suit your particular needs, for example
set(ha,'color','none'); %A transparent axis
set(ha,'xtick',[],'ytick',[]); %Remove tick labels
title(ha,'This is an inset plot')
Is the command subplot not what you're looking for?