Matlab: Plot a line over an image plot - matlab

I want to plot a line plot on top of an image plot in Matlab
First I plot the image data
figure(1); clf;
imagesc(t); colorbar
hold on;
axis tight
and then the line plot
line(ysum,y,'Color','red')
hold off;
The line plot however deletes the image and sets the background to white.
How can I plot on top of the image?

Your code isn't wrong, but it is not a minimal reproducible example, since you haven't defined t, y, ysum. When you call imagesc(t) the rows and columns will be the indices of t. In other words, it is the same as calling imagesc([1, size(t,2)], [1, size(t,1)], t). If t is small (say 10 x 10) but the elements of y,ysum are large (e.g. > 1000) then the 10 x 10 image will still be there, but it will be squished into the corner. Almost invisible.
So you need to make sure that the range of y, ysum, t line up. A quick work-around:
xidx = [min(ysum), max(ysum)];
yidx = [min(y), max(y)];
imagesc(xidx, yidx, t);

Related

How to keep plot size constant for two plots?

I'm using gramm to make two plots. I'm currently using
figure('position',[0,0,1000,1000])
So that each plot is graphed into the same size window. All of my fonts are the same size. However, plot A's X axis labels are shorter words than plot B's. This is causing matlab to shrink the size of the axis in plot B so that it can fit inside the window, which is causing plot A and B to be different sizes:
The actual images are the same size. However, the words take up more space in plot B, and so the actual plot is smaller. How can I tell matlab to keep the actual plots the same size?
Thanks in advance.
You can set the size for axis object, so change the axis size of Plot A to the axis size of plot B.
Click on Plot B to select it:
axisB = gca; % axis object for plot B
axisB.Units = 'pixels'; % or other absolute unit. Default is relative to figure
Now click on Plot A to select it:
axisA = gca;
axisA.Units = 'pixels'; % set to same unit as axisB
dHeight = axisA.Position(4) - axisB.Position(4);
axisA.Position(4) = axisB.Position(4); % set height of axisA to that of axisB
Optionally, you can reduce the figure size for plot A, so it looks better:
figA = gcf;
figA.Position(4) = figA.Position(4) - dHeight;

How to create a color gradient using a third variable in Matlab? [duplicate]

This question already has answers here:
Change color of 2D plot line depending on 3rd value
(5 answers)
Closed 5 years ago.
How do you create a color gradient in Matlab such that you plot a 2D line plot of y=y(x), and you color it using another variable that also depends on x such that z=z(x). A scatter or point plot is also fine by me.
I would also like to have a colormap legend kind of thing showing the color gradient and it's actual representation of z. This stuff is quite common in visualisation tools such as VisIt and ParaView but I could not yet FIGURE it out in Matlab.
If a scatter plot is fine, you can use the 4th input to scatter:
x = -10:0.01:10;
y = sinc(x);
z = sin(x);
scatter(x,y,[],z,'fill')
where z is the color.
The only way I know of to do this is with a little trick using surf:
% Create some sample data:
x = cumsum(rand(1,20)); % X data
y = cumsum(rand(1,20)); % Y data
z = 1:20; % "Color" data
% Plot data:
surf([x(:) x(:)], [y(:) y(:)], [z(:) z(:)], ... % Reshape and replicate data
'FaceColor', 'none', ... % Don't bother filling faces with color
'EdgeColor', 'interp', ... % Use interpolated color for edges
'LineWidth', 2); % Make a thicker line
view(2); % Default 2-D view
colorbar; % Add a colorbar
And the plot:
To manipulate the color of the line continuously, you'll want to use surface.
While at first look, this function looks most useful for plotting 3d surfaces, it provides more flexibility for line coloring than the basic plot function. We can use the edges of the mesh to plot our line, and take advantage of the vertex colors, C, to render interpolated color along the edge.
You can check out the full list of rendering properties, but the ones you are most likely to want are
'FaceColor', 'none', do not draw the faces
'EdgeColor', 'interp', interpolate between vertices
Here's an example adapted from MATLAB Answers post
x = 0:.05:2*pi;
y = sin(x);
z = zeros(size(x)); % We don't need a z-coordinate since we are plotting a 2d function
C = cos(x); % This is the color, vary with x in this case.
surface([x;x],[y;y],[z;z],[C;C],...
'FaceColor','none',...
'EdgeColor','interp');
Generate a colormap, e.g. jet(10). The example would generate a 10*3 matrix.
Use interp1 to interpolate between the values in the RGB space using your data by setting the first color as the lowest value and the last color as the highest value. This would generate a n*3 matrix where n is the number of data points.
Use scatter with the optional parameter c to plot the points with the interpolated colors.
activate colorbar to show the colorbar.

Xtick marks and Xtick labels on heatmap in Matlab

Environment: Windows 7 64 bit, Matlab 2014a
Objective:
To draw a heatmap of errors for two parameters to be optimized.
To put proper tick marks and tick values
Draw the grid lines in the correct place
Problem: Arranging the X and Y tick positions and values. When the last ("end") value of the vectors in x and y axes are the same, the code I use puts the ticks and values properly. However, when the end values are different it does not, and produces something really weird.
Below I have included the code which I have modified so that you can run it without the need of adding anything. Of course in my case the error vector are the error values, not random numbers. To see the problem of "end value" use the second b vector.
fontsize = 20
k = [2^-5, 2^-3, 2^-1, 2^0, 2^1, 2^3, 2^5, 2^7, 2^9, 2^11, 2^13, 2^15]
b = [2^-5, 2^-3, 2^-1, 2^0, 2^1, 2^3, 2^5, 2^7, 2^8, 2^9, 2^10, 2^11, 2^13, 2^15]
% b = [2^-5, 2^-3, 2^-1, 2^0, 2^1, 2^3, 2^5, 2^7, 2^8, 2^9, 2^10, 2^11, 2^13, 2^19]
errorVector = randi(20, 1, length(b)*length(k))'
figure
% Create a matrix from error vector (size of error vector is [length(k)*length(b),1])
B = reshape(errorVector, [length(b), length(k)])
B = flipud(B)
% imagesc(x,y,C)
imagesc(b, k, B)
title('Heatmap Parameters Percent Error', 'FontSize', fontsize);
% Set colorbar limits
caxis([0 15])
colorbar;
ax1 = gca;
xTickLabel = (k)'
xTick = linspace(k(1), k(end), numel(xTickLabel))';
set(ax1, 'XTick', xTick, 'XTickLabel', xTickLabel)
xlabel('k parameter', 'FontSize', fontsize)
yTickLabel = (b)'
yTick = linspace(b(1), b(end), numel(yTickLabel))';
set(ax1, 'YTick', yTick, 'YTickLabel', flipud(yTickLabel(:)))
ylabel('b parameter', 'FontSize', fontsize)
set(ax1,'FontSize', fontsize)
Here, change any of the end values of b or k vectors, and the program will output a graph where the X and Y ticks are totally wrong.
Also, I would like to draw grid lines. When I use "grid on" it draws grid lines right on the tick marks which is not correct in the case of heatmap. Because tick marks will be in the center of the columns -or rows- but the grid lines should be at the boundaries between the columns -or rows.
By the way if you know a better way to plot a heatmap in Matlab, please do tell.
Please help me solve this problem. Any help is appreciated,
Ilyas
First of all - you don't need to flipud the B matrix - by default imagesc plots the y-data inversed, but you can fix this with the following statement:
set(gca,'ydir','normal');
This also means you don't have to mess around with flipping the tick-labels. You can get the labels right by doing the following:
% replace the imagesc call with:
imagesc(B);
set(gca,'ydir','normal');
% formatting stuff
...
% replace the set commands with:
set(ax1, 'XTick', 1:length(k), 'XTickLabel', k)
set(ax1, 'YTick', 1:length(b), 'YTickLabel', b)
By default, if you don't provide x and y data to the imagesc command, it will number them linearly (1,2,3...). Basically what we've done here is make sure that it has ticks for each of the elements of b and k, and then set the labels to the values of the respective vectors.
Unfortunately, I'm not sure if there is a way to get the grid spacing right with imagesc or not. You could try using pcolor instead, which has it's own set of issues, but allows you to get grid lines (of sorts) between the elements. It also allows you to use an interpolated shading mode, which will make your plot look more like a typical heat map.
To use pcolor instead, you just have to replace imagesc:
% imagesc(B);
% set(gca,'ydir','normal');
pcolor(B);
% this uses a smoother shading method, for a more 'heatmap' like output
% shading interp
Everything else should work as intended, I believe.

Moving MATLAB axis ticks by a half step

I'm trying to position MATLAB's ticks to line up with my grid, but I can't find a good way to offset the labels.
Also, if I run set(gca,'XTickLabel',1:10), my x tick labels end up ranging from 1 to 5. What gives?
You need to move the ticks, but get the labels before and write them back after moving:
f = figure(1)
X = randi(10,10,10);
surf(X)
view(0,90)
ax = gca;
XTick = get(ax, 'XTick')
XTickLabel = get(ax, 'XTickLabel')
set(ax,'XTick',XTick+0.5)
set(ax,'XTickLabel',XTickLabel)
YTick = get(ax, 'YTick')
YTickLabel = get(ax, 'YTickLabel')
set(ax,'YTick',YTick+0.5)
set(ax,'YTickLabel',YTickLabel)
Or if you know everything before, do it manually from the beginning:
[N,M] = size(X)
set(ax,'XTick',0.5+1:N)
set(ax,'XTickLabel',1:N)
set(ax,'YTick',0.5+1:M)
set(ax,'YTickLabel',1:M)
The marked answer works with a surf or mesh plot, however, I needed a solution which worked for a 2d plot.
This can be done by creating two axes, one to display the grid and the other to display the labels as follows
xlabels=1:1:10; %define where we want to see the labels
xgrid=0.5:1:10.5; %define where we want to see the grid
plot(xlabels,xlabels.^2); %plot a parabola as an example
set(gca,'xlim',[min(xgrid) max(xgrid)]); %set axis limits so we can see all the grid lines
set(gca,'XTickLabel',xlabels); %print the labels on this axis
axis2=copyobj(gca,gcf); %make an identical copy of the current axis and add it to the current figure
set(axis2,'Color','none'); %make the new axis transparent so we can see the plot
set(axis2,'xtick',xgrid,'XTickLabel',''); %set the tick marks to the grid, turning off labels
grid(axis2,'on'); %turn on the grid
This script displays the following figure :

MATLAB, Filling in the area between two sets of data, lines in one figure

I have a question about using the area function; or perhaps another function is in order...
I created this plot from a large text file:
The green and the blue represent two different files. What I want to do is fill in the area between the red line and each run, respectively. I can create an area plot with a similar idea, but when I plot them on the same figure, they do not overlap correctly. Essentially, 4 plots would be on one figure.
I hope this makes sense.
Building off of #gnovice's answer, you can actually create filled plots with shading only in the area between the two curves. Just use fill in conjunction with fliplr.
Example:
x=0:0.01:2*pi; %#initialize x array
y1=sin(x); %#create first curve
y2=sin(x)+.5; %#create second curve
X=[x,fliplr(x)]; %#create continuous x value array for plotting
Y=[y1,fliplr(y2)]; %#create y values for out and then back
fill(X,Y,'b'); %#plot filled area
By flipping the x array and concatenating it with the original, you're going out, down, back, and then up to close both arrays in a complete, many-many-many-sided polygon.
Personally, I find it both elegant and convenient to wrap the fill function.
To fill between two equally sized row vectors Y1 and Y2 that share the support X (and color C):
fill_between_lines = #(X,Y1,Y2,C) fill( [X fliplr(X)], [Y1 fliplr(Y2)], C );
You can accomplish this using the function FILL to create filled polygons under the sections of your plots. You will want to plot the lines and polygons in the order you want them to be stacked on the screen, starting with the bottom-most one. Here's an example with some sample data:
x = 1:100; %# X range
y1 = rand(1,100)+1.5; %# One set of data ranging from 1.5 to 2.5
y2 = rand(1,100)+0.5; %# Another set of data ranging from 0.5 to 1.5
baseLine = 0.2; %# Baseline value for filling under the curves
index = 30:70; %# Indices of points to fill under
plot(x,y1,'b'); %# Plot the first line
hold on; %# Add to the plot
h1 = fill(x(index([1 1:end end])),... %# Plot the first filled polygon
[baseLine y1(index) baseLine],...
'b','EdgeColor','none');
plot(x,y2,'g'); %# Plot the second line
h2 = fill(x(index([1 1:end end])),... %# Plot the second filled polygon
[baseLine y2(index) baseLine],...
'g','EdgeColor','none');
plot(x(index),baseLine.*ones(size(index)),'r'); %# Plot the red line
And here's the resulting figure:
You can also change the stacking order of the objects in the figure after you've plotted them by modifying the order of handles in the 'Children' property of the axes object. For example, this code reverses the stacking order, hiding the green polygon behind the blue polygon:
kids = get(gca,'Children'); %# Get the child object handles
set(gca,'Children',flipud(kids)); %# Set them to the reverse order
Finally, if you don't know exactly what order you want to stack your polygons ahead of time (i.e. either one could be the smaller polygon, which you probably want on top), then you could adjust the 'FaceAlpha' property so that one or both polygons will appear partially transparent and show the other beneath it. For example, the following will make the green polygon partially transparent:
set(h2,'FaceAlpha',0.5);
You want to look at the patch() function, and sneak in points for the start and end of the horizontal line:
x = 0:.1:2*pi;
y = sin(x)+rand(size(x))/2;
x2 = [0 x 2*pi];
y2 = [.1 y .1];
patch(x2, y2, [.8 .8 .1]);
If you only want the filled in area for a part of the data, you'll need to truncate the x and y vectors to only include the points you need.