Colorbar limits not respecting axes clims when displaying an image - matlab

Im trying to superimpose a trimesh-plot over a image imshow using hold on. This works fine so far. I'd additionally like to display a colorbar, which works too, but unfortunately it does not adjust to the range specified by caxis, does anyone have an idea how to fix this?
This is an example output: The colourbar should display a range from 1 to z, not from 0 to 60. If we remove imshow everything works fine.
Here my MCVE:
clc;clf;clear
T = [1,2,3;3,1,4]; % triangulation
X = [0,1,1,0]*300; % grid coordinates
Y = [0,0,1,1]*300;
for z = 2:20;
clf;
imshow(imread('board.tif')) % plot image (this is a built in matlab test image)
hold on
Z = [1,1,1,z];
trisurf(T,X,Y,Z) % superimpose plot
colormap hot
caxis([1,z])
colorbar
drawnow
pause(0.5)
end

This appears to be a bug in how older versions of MATLAB handled the colorbar (it's not present with HG2). The "correct" behavior would be that if you have any objects in the current axes that use scaled values, then the colorbar should respect your clims. It seems that MATLAB is using the first child in the current axes to determine whether to respect your clims or not. imshow does not use scaled CDataMapping so colorbar simply ignores your clims.
It looks like you have three options:
Use imagesc rather than imshow
clf;
imagesc(imread('board.tif'));
axis image
hold on
Z = [1,1,1,z];
trisurf(T,X,Y,Z) % superimpose plot
colormap hot
caxis([1,z])
drawnow
colorbar
drawnow
pause(0.5)
Call imshow after you've created your trisurf object
clf;
hold on
Z = [1,1,1,z];
trisurf(T,X,Y,Z) % superimpose plot
colormap hot
him = imshow(imread('board.tif'));
caxis([1,z])
drawnow
colorbar
drawnow
pause(0.5)
Set the CDataMapping property of the image object to 'scaled' (will be ignored when displaying the image since it's RGB but it will allow the colorbar to function properly)
clf;
him = imshow(imread('board.tif'));
set(him, 'CDataMapping', 'scaled')
hold on
Z = [1,1,1,z];
trisurf(T,X,Y,Z) % superimpose plot
colormap hot
caxis([1,z])
drawnow
colorbar
drawnow
pause(0.5)

Related

MATLAB: Color of sphere distorts color scheme values

I have the following MWE, showing a surf-plot and a sphere,
figure(1)
[xx yy] = meshgrid(0:0.1:pi, 0:0.1:pi);
surf(xx, yy, zeros(size(xx)), 0.001*sin(xx), 'EdgeColor', 'none')
hold on
[xS,yS,zS] = sphere(50);
surf(xS+1, yS+1, zS+1,'FaceColor', 'k', 'edgecolor','none')
hold off
colorbar
The amplitude of the surf-plot is so small that one cannot see what value it has wrt. the colorbar. This is due to the sphere, which has a large amplitude and "distorts" everything.
Is there a way to somehow force the figure to not take into account the color of the sphere? Or maybe change its "amplitude"? I tried changing caxis, but it doesn't make a difference.
Set up manually the limits of your colorbar with caxis
your colors are C=0.001*sin(xx)
then, after the plotting, add caxis([min(C(:)) max(C(:))]) and you will have the limits are you wish

Plotting in GUI of Matlab

Until now i had only 1 axis in my GUI to I used to just plot directly using plot command. Plus i need to plot these in a loop.
for i = 1:length(sig)
plot(sig(i).time,sig(i).signal,sig(i).time,updated(i).filter,)
hold on
end
Now i have 2 axes in my GUI, how can I make a certain plot appear in 1st axis and another in my 2nd axis
Now for example i need to plot the below in the 2nd axis
for i = 1:length(sig)
plot(sig(i).time,sig(i).fil,sig(i).time,updated(i).sig,)
hold on
end
Any help will be appriciated
You could specify the axes for hold and plot functions. Considering you have two axes, h1 and h2 inside your figure, you could do the following:
hold(h1, 'on')
hold(h2, 'on')
for i = 1:length(sig)
plot(h1, sig(i).time,sig(i).signal,sig(i).time,updated(i).filter)
plot(h2, sig(i).time,sig(i).fil,sig(i).time,updated(i).sig)
end

How to use a colormap in matlab?

I'd like to read a custom image and apply a colormap like in the example from matlab. How can I do that? I see the example imageext uses custom images and applies colormaps and I'd like to do the same with my images. How can it be done? I want just to use my own picture for an example like imageext in matlab.
This does not work:
I = im2double(imread('niklas3.png')); figure(1); imshow(I,[]); daspect([1 1 1]); axis off; colormap gray;
niklas3.png:
But this code works:
I = im2double(imread('cameraman.tif')); figure(1); imshow(I,[]); daspect([1 1 1]); axis off; colormap summer;
You can apply a colormap in any image you want if it was previously displayed into a figure.
I recommend you to use imagesc or imshow to display images. In order to do that, you need to load the image with imread. A good practice is to convert your image data to double precision.
I = im2double(imread('cameraman.tif'));
As you can see, im2double converts image data to double precision ranging from 0 values to 1 values. If you do not want this, you can use the double function, ranging from 0 values to 255 value.
Later, you need to display the image into a figure. I strongly recommend to use imagesc instead of imshow, because imagesc allows you to customize your data and your display (for example, adding a different colormap).
figure(1); imagesc(I); daspect([1 1 1]); axis off;
Now, you can use the colormap you want. Type help colormap for more information, but you can use a jet colormap (default), gray, hot, bones, or whatever you want, just typing:
colormap gray;
If you plotted several images, you need to indicate the aimed image with:
figure(1); colormap gray;
If you want to use imshow, just type:
figure(1); imshow(I,[]); daspect([1 1 1]); axis off; colormap gray;
Edited: Once I saw your image, I knew your problem is that you are trying to apply a colormap into a RGB image. That is, you are trying to apply it into a 3D matrix, where rows and columns identify the pixel value and the third dimension identifies the RGB components.
So, you need to convert your RGB image into a 2D matrix (a black and white one). You can do it by performing the mean along the third dimension.
I = nanmean(I,3);
Finally, you should apply the colormap as I said it before. The final code would be:
I = im2double(imread('niklas3.jpg'));
I = nanmean(I,3);
figure(1); imshow(I,[]); daspect([1 1 1 ]); axis off;
colormap jet;
This is the result using a jet colormap:

How can I make a "color map" plot in matlab?

I have some data (a function of two parameters) stored in a matlab format, and I'd like to use matlab to plot it. Once I read the data in, I use mesh() to make a plot. My mesh() plot gives me the the value of the function as a color and a surface height, like this:
What matlab plotting function should I use to make a 2D mesh plot where the dependent variable is represented as only a color? I'm looking for something like pm3d map in gnuplot.
By default mesh will color surface values based on the (default) jet colormap (i.e. hot is higher). You can additionally use surf for filled surface patches and set the 'EdgeColor' property to 'None' (so the patch edges are non-visible).
[X,Y] = meshgrid(-8:.5:8);
R = sqrt(X.^2 + Y.^2) + eps;
Z = sin(R)./R;
% surface in 3D
figure;
surf(Z,'EdgeColor','None');
2D map: You can get a 2D map by switching the view property of the figure
% 2D map using view
figure;
surf(Z,'EdgeColor','None');
view(2);
... or treating the values in Z as a matrix, viewing it as a scaled image using imagesc and selecting an appropriate colormap.
% using imagesc to view just Z
figure;
imagesc(Z);
colormap jet;
The color pallet of the map is controlled by colormap(map), where map can be custom or any of the built-in colormaps provided by MATLAB:
Update/Refining the map: Several design options on the map (resolution, smoothing, axis etc.) can be controlled by the regular MATLAB options. As #Floris points out, here is a smoothed, equal-axis, no-axis labels maps, adapted to this example:
figure;
surf(X, Y, Z,'EdgeColor', 'None', 'facecolor', 'interp');
view(2);
axis equal;
axis off;
gevang's answer is great. There's another way as well to do this directly by using pcolor. Code:
[X,Y] = meshgrid(-8:.5:8);
R = sqrt(X.^2 + Y.^2) + eps;
Z = sin(R)./R;
figure;
subplot(1,3,1);
pcolor(X,Y,Z);
subplot(1,3,2);
pcolor(X,Y,Z); shading flat;
subplot(1,3,3);
pcolor(X,Y,Z); shading interp;
Output:
Also, pcolor is flat too, as show here (pcolor is the 2d base; the 3d figure above it is generated using mesh):
Note that both pcolor and "surf + view(2)" do not show the last row and the last column of your 2D data.
On the other hand, using imagesc, you have to be careful with the axes. The surf and the imagesc examples in gevang's answer only (almost -- apart from the last row and column) correspond to each other because the 2D sinc function is symmetric.
To illustrate these 2 points, I produced the figure below with the following code:
[x, y] = meshgrid(1:10,1:5);
z = x.^3 + y.^3;
subplot(3,1,1)
imagesc(flipud(z)), axis equal tight, colorbar
set(gca, 'YTick', 1:5, 'YTickLabel', 5:-1:1);
title('imagesc')
subplot(3,1,2)
surf(x,y,z,'EdgeColor','None'), view(2), axis equal tight, colorbar
title('surf with view(2)')
subplot(3,1,3)
imagesc(flipud(z)), axis equal tight, colorbar
axis([0.5 9.5 1.5 5.5])
set(gca, 'YTick', 1:5, 'YTickLabel', 5:-1:1);
title('imagesc cropped')
colormap jet
As you can see the 10th row and 5th column are missing in the surf plot. (You can also see this in images in the other answers.)
Note how you can use the "set(gca, 'YTick'..." (and Xtick) command to set the x and y tick labels properly if x and y are not 1:1:N.
Also note that imagesc only makes sense if your z data correspond to xs and ys are (each) equally spaced. If not you can use surf (and possibly duplicate the last column and row and one more "(end,end)" value -- although that's a kind of a dirty approach).
I also suggest using contourf(Z). For my problem, I wanted to visualize a 3D histogram in 2D, but the contours were too smooth to represent a top view of histogram bars.
So in my case, I prefer to use jucestain's answer. The default shading faceted of pcolor() is more suitable.
However, pcolor() does not use the last row and column of the plotted matrix. For this, I used the padarray() function:
pcolor(padarray(Z,[1 1],0,'post'))
Sorry if that is not really related to the original post

How to make 1-D plots in MATLAB?

How can I make plots in MATLAB like in below?
I won't need labels, so you can ignore them. I tried using normal 2D plot, by giving 0 to y parameter for each data points. It does help, but most of the plot remains empty/white and I don't want that.
How can I solve this problem?
Edit:
This is how I plot(playing with values of ylim does not help):
hold on
for i=1:120
if genders(v_labels(i)) == CLASS_WOMAN
plot(v_images_lda(i,:) * w_lda,0,'r*');
else
plot(v_images_lda(i,:) * w_lda,0,'b.');
end
end
title('LDA 1D Plot');
ylim([-0.2 0.2]);
hold off
One way to do this would be to adjust the 'XLim', 'YLim', and 'DataAspectRatio' properties of the axes so that it renders as essentially a single line. Here's an example:
data1 = rand(1,20)./2; %# Sample data set 1
data2 = 0.3+rand(1,20)./2; %# Sample data set 2
hAxes = axes('NextPlot','add',... %# Add subsequent plots to the axes,
'DataAspectRatio',[1 1 1],... %# match the scaling of each axis,
'XLim',[0 1],... %# set the x axis limit,
'YLim',[0 eps],... %# set the y axis limit (tiny!),
'Color','none'); %# and don't use a background color
plot(data1,0,'r*','MarkerSize',10); %# Plot data set 1
plot(data2,0,'b.','MarkerSize',10); %# Plot data set 2
And you will get the following plot:
Here's one way to reproduce your figure using dsxy2figxy and annotate. dsxy2figxy can be hard to find the first time, as it is not really in your path. It is part of the MATLAB package and is provided in the example functions. You can reach it by searching for it in the help docs and once you find it, open it and save it to a folder in your path.
h1=figure(1);clf
subplot(4,1,1);
hold on
xlim([0.2,1]);ylim([-1,1])
%arrow
[arrowX,arrowY]=dsxy2figxy([0.2,1],[0,0]);
annotation('arrow',arrowX,arrowY)
%crosses
x=[0.3,0.4,0.6,0.7,0.75];
plot(x,0,'kx','markersize',10)
%pipes
p=[0.5,0.65];
text(p,[0,0],'$$\vert$$','interpreter','latex')
%text
text([0.25,0.5,0.65],[1,-1,-1]/2,{'$$d_i$$','E[d]','$$\theta$$'},'interpreter','latex')
axis off
print('-depsc','arrowFigure')
This will produce the following figure:
This is sort of a hackish way to do it, as I've tricked MATLAB into printing just one subplot. All rasterized formats (jpeg, png, etc) will not give you the same result, as they'll all print the entire figure including where the non-declared subplots should've been. So to get this effect, it has to be an eps, and it works with it because eps uses much tighter bounding boxes... so all the meaningless whitespace is trimmed. You can then convert this to any other format you want.
Ok so the closest I have come to solving this is the following
hax = gca();
hold on
for i=1:120
if genders(v_labels(i)) == CLASS_WOMAN
plot(v_images_lda(i,:) * w_lda,0,'r*');
else
plot(v_images_lda(i,:) * w_lda,0,'b.');
end
end
set(hax, 'visible', 'off');
hax2 = axes();
set(hax2, 'color', 'none', 'ytick', [], 'ycolor', get(gcf, 'color');
pos = get(hax, 'position');
set(hax2, 'position', [pos(1), pos(2)+0.5*pos(4), pos(3), 0.5*pos(4)]);
title('LDA 1D Plot');
hold off
So in short, I hid the original axis and created a new one located at 0 of the original axis, and as I couldn't remove the y axis completely I set it's color to the background color of the figure.
You can then decide if you also want to play with the tick marks of the x-axis.
Hope this helps!
Very naive trick but a useful one.
Plot in 2d using matlab plot function. Then using edit figure properties compress it to whichever axis you need a 1D plot on !! Hope that helps :)