How to set matlab xticks equal distance with unequal numerical spaces? - matlab

I am plotting data which is polynomial but I would like to show it on a straight line so that it is clearer.
I want the x-axis tick marks to show N^2 where N is the tick location. I also want the actual ticks on the graph to be evenly spaced even though the numbers aren't.
I tried to change the ticks using
xtick_squared = (0:10:100).^2
set(gca,'xTick',xtick_squared,'xTickLabel',xtick_squared)
but it gives this
How can I display them each being even spaced while reatining their values as well as adjusting the data?

This should work fine:
x = 0:10:100;
y = (x .^ 2) + 5;
labs = sprintfc('%d',x.^2);
plot(x,y);
set(gca,'XTickLabel',labs);
Actually, it's all about changing the tick labels without changing the ticks themselves. Here is the final output:

You can specify the location of x-ticks and then rename them.
Here is the code example:
x=[0,10,20,30,40,50].^2;
plot(x,x)
set(gca,'XTick',linspace(0,2500,6),'XTickLabels',num2cell(x))
P.S.: Note, that your actual data is plotted on evenly spaced grid. I've just renamed the ticks' names.
Edit: if you want to plot your actual data, you need to scale x-axis correspondingly. If you want to plot(x,x) you need to call plot(sqrt(x),x) instead:
x=[0,10,20,30,40,50].^2;
plot(sqrt(x),x)
set(gca,'XTick',linspace(0,2500,6),'XTickLabels',num2cell(x))

Related

Matlab 2016a - how to get xTickLabels on only some of the xTicks on an imagesc?

I'm trying to create a 24x366 heatmap using imagesc with the x-axis labelled at 13 evenly spaced points as {'jan 15','feb 15',...,'dec 15','jan 16'}, and the y-axis labelled at every row from 1 to 24, like this:
Desired imagesc axes
When I run the script, it displays the y-axis as I want it, but it only displays the first label on the x axis and ignores the others. I can get this to work for a plot, but I can't get it to work for an imagesc. I've included my script below. Does anyone know how to make the imagesc display all 13 labels on the x-axis at evenly spaced intervals?
mylabels = {'jan 15','feb 15','mar 15','apr 15','may 15','jun 15','jul 15','aug 15','sep 15','oct 15','nov 15','dec 15','jan 16'};
testspacing = (1:(60*24*30):528480);
figure
imagesc(rand(24,366))
set(gca,'XTick',testspacing,'XTickLabel',mylabels,'XTickLabelRotation',45,'YTick',1:24,'YTickLabel',1:24)
The problem with your code is that your only one of your ticks from testspacing falls in the range of the plot testspacing=[1 43201 ...]. You can check the range of your x-axis by running xlim without any arguments.
You can rescale testspacing to fit your x-axis e.g. like:
xmax = 366;
mylabels = {'jan 15','feb 15','mar 15','apr 15','may 15','jun 15','jul 15','aug 15','sep 15','oct 15','nov 15','dec 15','jan 16'};
testspacing = (1:(60*24*30):528480);
testspacing = testspacing/max(testspacing)*xmax;
figure
imagesc(rand(24,xmax))
set(gca,'XTick',testspacing,'XTickLabel',mylabels,'XTickLabelRotation',45,'YTick',1:24,'YTickLabel',1:24)
or you just generate testspacing properly. Since you are putting own labels on the axis anyway you might just choose use testspacing = [0:30.5:366] or testspacing = [0:30:366] depending on what you want. This will also help you debug your own code later on.
On another note you should think about reducing the number of labels in general and decide which of the labels are really helpful. Maybe every 2nd or 3rd month is enough. You can "remove" individual labels by setting them to empty strings ''.

Draw evenly-spaced height lines of a function in MATLAB

I would like to draw height lines of a function (represented by matrices, of course), using MATLAB.
I'm familiar with contour, but contour draws lines at even-spaced heights, while I would like to see lines (with height labels), in constant distance from one another when plotted.
This means that if a function grows rapidly in one area, I won't get a plot with dense height lines, but only a few lines, at evenly spaced distances.
I tried to find such an option in the contour help page, but couldn't see anything. Is there a built in function which does it?
There is no built-in function to do this (to my knowledge). You have to realize that in the general case you can't have lines that both represent iso-values and that are spaced with a fixed distance. This is only possible with plots that have special scaling properties, and again, this is not the general case.
This being said, you can imagine to approach your desired plot by using the syntax in which you specify the levels to plots:
...
contour(Z,v) draws a contour plot of matrix Z with contour lines at the data values specified in the monotonically increasing vector v.
...
So all you need is the good vector v of height values. For this we can take the classical Matlab exemple:
[X,Y,Z] = peaks;
contour(X,Y,Z,10);
axis equal
colorbar
and transform it in:
[X,Y,Z] = peaks;
[~, I] = sort(Z(:));
v = Z(I(round(linspace(1, numel(Z),10))));
contour(X,Y,Z,v);
axis equal
colorbar
The result may not be as nice as what you expected, but this is the best I can think of given that what you ask is, again, not possible.
Best,
One thing you could do is, instead of plotting the contours at equally spaces levels (this is what happens when you pass an integer to contour), to plot the contours at fixed percentiles of your data (this requires passing a vector of levels to contour):
Z = peaks(100); % generate some pretty data
nlevel = 30;
subplot(121)
contour(Z, nlevel) % spaced equally between min(Z(:)) and max(Z(:))
title('Contours at fixed height')
subplot(122)
levels = prctile(Z(:), linspace(0, 100, nlevel));
contour(Z, levels); % at given levels
title('Contours at fixed percentiles')
Result:
For the right figure, the lines have somewhat equal spacing for most of the image. Note that the spacing is only approximately equal, and it is impossible to get the equal spacing over the complete image, except in some trivial cases.

How to set x and y values when using bar3 in Matlab?

Quick version
How can I control the x- and y-values for a 3-d bar plot in Matlab?
Details
Say we have an 10 x 20 data matrix and we plot it using bar3, and we want to set the x- and y-values. For instance:
foodat = rand(10,20);
xVals = [5:14];
yVals = [-3:16];
bar3(xVals, foodat);
xlabel('x'); ylabel('y');
Is there a way to feed it the yVals as well? Otherwise the y axes always defaults to [1:N].
Note I don't just want to change the labels using XTickLabel and YTickLabel. I need to change the actual values on the axes, because I am plotting multiple things in the same figure. It isn't enough to just change how the (wrong) axis ticks are labeled. So this is different from issues like this:
How can I adjust 3-D bar grouping and y-axis labeling in MATLAB?
Other things I have tried
When I try changing the xvals with:
set(gca,'XTick', xVals)
set(gca,'YTick', yVals)
The values are taken in, but actually show up on the wrong axes, so it seems x and y axes are switched using bar3. Plus, it is too late anyway as the bar graph was already plotted with the wrong x- and y-values, so we would end up giving ticks to empty values.
Note added
Matlab tech support just emailed me to let me know about the user contributed function scatterbar3, which does what I want, in a different way than the accepted answer:
http://www.mathworks.com/matlabcentral/fileexchange/1420-scatterbar3
I found a way of doing it. Ill give you a piece of code, then you'll need to "tidy up" , mainly the axis limits and the Xticks, as bar3 does set up the Xticks inside, so if you want others you'll need to set them manually yourself.
So the trick here is to get the Xdata from the bar3 handle. The thing here is that it seems that there is a handle for each row of the data, so you need to iterate for each of them. Here is the code with the current output:
foodat = rand(20,10);
xVals = [5:14];
yVals = [-3:16];
% The values of Y are OK if called like this.
subplot(121)
bar3(yVals, foodat);
subplot(122)
h=bar3(yVals, foodat);
Xdat=get(h,'XData');
axis tight
% Widdth of barplots is 0.8
for ii=1:length(Xdat)
Xdat{ii}=Xdat{ii}+(min(xVals(:))-1)*ones(size(Xdat{ii}));
set(h(ii),'XData',Xdat{ii});
end
axis([(min(xVals(:))-0.5) (max(xVals(:))+0.5) min(yVals(:))-0.5, max(yVals(:))+0.5])
Note: Y looks different but is not.
As you can see now the X values are the ones you wanted. If you'd want other size than 1 for the intervals between them you'd need to change the code, but you can guess how probably!

Making an accurate colorbar for a simple plot

I am trying to make a simple plot (for this example doing a plot of y=x^2 will suffice) where I want to set the colors of the points based on their magnitude given some colormap.
Following along my simple example say I had:
x = 1:10;
y = x.^2;
Use gscatter(x,y,jet(10)); legend hide; colorbar which produces a plot with the points colored but the colorbar does not agree with the colored values. (Can't post picture as this is my first post). Using a caxis([1,100]) command gives the right range but the colors are still off.
So I have two questions:
(1) How can I fix the colors to fit to a colorbar given a range? In my real data, I am looking at values that range from -50 to 50 in some instances and have many more data points.
(2) I want to create a different plot with the same points (but on different axes) and I want the colors of each point on this new plot to have the same colors as their counterparts in the previous plot. How can I, programmatically, extract the color from each point so I can plot it on two different sets of axes?
I would just move the points into a matrix and do an imagesc() command but they aren't spaced as integers or equally so simple scaling wouldn't work either.
Thanks for any help!
Regarding you first question, you need to interpolate the y values into a linear index to the colormap. Something like:
x = 1:10;
y = x.^4;
csize = 128;
cmap = jet(csize);
ind = interp1(linspace(min(y),max(y),csize),1:csize,y,'nearest');
scatter(x,y,14,cmap(ind,:),'filled')
colorbar
caxis([min(y) max(y)])
Using interp1 in this case is an overkill; you could calculate it directly. However, I think in this way it is clearer.
I think it also answers your 2nd question, since you have the index of the color of each data point, so you can use it again in the same way.

MATLAB: Density-time Plot

I have 11 1x50 matrices that contain densities. The first looks like [20, 20, 20... 20] and represents time=0. The second looks like [20, 19, 22,..], etc. and represents time=100. These continue to vary until t=1000.
What I'm hoping to do is to create a plot with the elements' position on the x-axis (50 positions for the 50 pieces of data in each) and time (0-1000) on the y-axis. Ideally, I'd like the plot to be completely filled in with color densities, and a colorbar on the side that shows what densities the color range represents.
Any help would be greatly appreciated!
Sort of inspired by: http://www.chrisstucchio.com/blog/2012/dont_use_scatterplots.html
Assuming you have (or can arrange to have) all those vectors as columns of a 11x50 matrix:
A = randi(100, 11,50); %//example data
you can just use
imagesc(1:50, 0:100:1000, A)
colorbar
axis xy %// y axis increasing, not decreasing
Example:
Looking at the comments, it will be easier to stack these vectors into a 2D matrix. You have 11 individually named vectors. Assuming that your vectors are named vec1, vec2, vec3, etc., create a 2D matrix A that stacks these vectors on top of each other. Also, you'll need to include an extra row and column at the end of this matrix that contains the minimum over all of your vectors. The reason why this is will be apparent later, but for now take my word for it as this is what you need.
In other words:
A = [vec1; vec2; vec3; vec4; vec5; vec6; vec7; vec8; ...
vec9; vec10; vec11];
minA = min(A(:));
A = [A minA*ones(11,1); minA*ones(1,51)];
As such, the first row contains the information at time 0, the next row contains information at time 100, etc. up to time 1000.
Now that we have that finished, we can use the pcolor function to plot this data for you. pcolor stands for pseudo-coloured checkerboard plot. You call this by doing:
pcolor(A);
This will take a matrix stored in A and produce a checkerboard plot of your data. Each point in your matrix gets assigned a colour. The colours get automatically mapped so that the least value gets mapped to the lowest colour while the highest value gets mapped to the highest colour. pcolor does not plot the last row and last column of the matrix, but pcolor does use all of the data in the matrix. In order to ensure that the colours get properly mapped, we need to pad your matrix so that the last row and last column get assigned to the smallest value over all of your vectors. As you want to plot all values in the matrix, that's why we did what we did above.
Once we do this, we'll need to modify the X and Y ticks so that it conforms to your data. As such:
pcolor(A);
set(gca, 'XTick', 0.5:5:51.5);
set(gca, 'XTickLabel', 0:5:50);
set(gca, 'YTick', 1.5:11.5);
set(gca, 'YTickLabel', 0:100:1000);
xlabel('Sample Number');
ylabel('Time');
colorbar;
What the code does above is that it generates a checkerboard pattern like what we talked about. This labels the Sample Number on the x axis while time is on the y axis. You'll see with the two set commands that I did, this is a bit of a hack. The y axis by default labeled the ticks going from 1 - 12. What I did was that I changed these labels so that they go from 0 to 1000 in steps of 100 instead and I also removed the tick of 12. In addition, I have made sure that these labels go in the middle of each row. I do this by setting the YTick property so that I add 0.5 to each value going from 1 - 11. Once I do this, I then change the labels so that they go from 0 - 1000 in steps of 100. I also do the same for the x axis in a similar fashion to the y axis. I then add a colorbar to the side as per your request.
Following the above code, and generating random integer data that is between 13 and 27 as per your comments:
A = randi([13,27], 11, 50);
minA = min(A(:));
A = [A minA*ones(11,1); minA*ones(1,51)];
We get:
Obviously, the limits of the colour bar will change depending on the dynamic range of your data. I used randi and generated random integers within the range of 13 to 27. When you use this code for your purposes, the range of the colour bar will change depending on the dynamic range of your data, but the colours will be adjusted accordingly.
Good luck!