How to set x axis values in MATLAB - matlab

I'm working with some signal. The signal has some length (time) and I devided it into 200 pieces and made some operations over them. The results are saved in matrix, so the matrix has one of the dimensions 200 and if I use imagesc() on it, to make results visualy readable, the x axis is from 0 to 200. But that does not correspond to time. The time is function of the values in x axis.
t = 640 * x
I need to make values in x axis to correspond to time. Is there any way, how to do this?

Use set and set the XTick and the XTickLabel properties accordingly. Assuming your image is already open, do this:
set(gca, 'XTick', 0:20:200);
set(gca, 'XTickLabel', 640*(0:20:200));
I used increments of 20 so that you don't clutter the x-axis. Modify the 20 to suit your tastes.

Related

How to change axis limits and tick step of a MatLab figure?

I have a simple plot of y against x.
y = [6,-1.3,-8,-11.7,-11,-6,1.3,8,11.7,11,6,-1.3];
x = 0:0.3:3.3;
plot (x,y)
As the result, the x-axis of the figure is ranging from 0 to 3.5, with scale of 0.5. I have used the XLimit = [0 3.3] to limit the axis, but it seems like not working.
I wish to make the x-axis range from 0 to 3.3 with steps of 0.3.
axis tight % removes the empty space after 3.3
set(gca,'XTick',0:0.3:3.3) % sets the x axis ticks
With XLimit = [0 3.3] you just define a vector called XLimit. In order to use this vector as horizontal limit, you should use xlim:
xlim(XLimit)
% or directly:
xlim([0, 3.3])
Read more about xlim here. Similarly you can set the vertical limit with ylim.
Since you are trying to set the limits equal to the range of x, you will probably find the following command most helpful:
axis tight
But note that it changes both x- and y-axis limits.
To set the tick step, as AVK said, you should set the 'XTick' to 0:0.3:3.3:
set(gca,'XTick',0:0.3:3.3)
gca is the handle to current axes.

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!

Matlab plotting through origin regardless of only negative or only positive data

this one should be really easy to answer, yet I am surprised it is nowhere described:
I have variable data, and often when I simply plot, I get a close-up on the y-axis (x-axis is time and starts always with a zero). So I get y-values from 16-17, but the zero is nowhere to be seen. I know you can give matlab an YLim value, yet sometimes because my data is variable, I get a range from -50-100 in y. If i had specified before that YLim is [0 20] I wouldnt see it at all, which is not what I want. I just always want to have the origin plotted with my data, how do I do that (without a rigid interval like [-1000 1000], since sometimes I have y values from -0,01-0,001 and wouldnt see it)? Please help if you have an idea!
Thanks!
UPDATE 1: perfectly solved!
Follow-up question:
There is one thing I didnt mention: I need to do this for all my 18 subplots. How can I avoid hardcoding it?
One way to do this is automatically is to use:
ylim([min([y 0]) max([y,0])])
this way, it will start or stop at 0 if 0 is not already in the range of y
or better, if you want to keep the rounded values matlab provides (eg plot on [0,6] and not on [0,5.872]), first plot your data with plot(x,y), then change the ylim values to 0 if needed:
ylim([min([ylim 0]) max([ylim 0])])
It's easy to manually modify axis size:
x = 1:10; %/ example x
y = 5 + rand(1,10); %// example y. Values between 5 and 6
plot(x,y) %// do the plot normally
ax = axis; %// get axis size
ax(3) = min(ax(3),0); %// if the y-axis lower limit is positive, make it 0
axis(ax) %// apply new axis size values
This also seems to work: just use
plot([x NaN],[y 0])
That is, include a point with x value set to NaN and y value set to 0. The point doesn't get plotted (because of the NaN value) but it forces the y axis to strech out to 0.

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!

axis equal in a Matlab loglog plot

In Matlab the command 'axis equal':
sets the aspect ratio so that equal tick mark
increments on the x-,y- and z-axis are equal in size. This
makes SPHERE(25) look like a sphere, instead of an ellipsoid
However, when using the loglog plotting function, this doesn't work "properly". What I would like to happen is that I get an aspect ratio so that a given factor occupies the same visual distance. What actually happens is that
>> loglog(2.^[1:20]*1e10,(2.^[1:20]).^2)
>> axis equal
results in
rather than
So that the slope 2 (from the squared) could be easily observed, and so that there wouldn't be all that extra white space.
My question is:
Is there a Matlab command that does this for me? Alternatively, has anyone solved this problem before?
One solution is for you to modify the axes limits and 'DataAspectRatio' properties yourself so that a decade on one axis equals a decade on the other. Here's how you can do it for your example:
loglog(2.^[1:20]*1e10,(2.^[1:20]).^2); %# Plot your sample data
xLimits = [1e10 1e16]; %# Limits for the x axis
yLimits = [1 1e12]; %# Limits for the y axis
logScale = diff(yLimits)/diff(xLimits); %# Scale between the x and y ranges
powerScale = diff(log10(yLimits))/... %# Scale between the x and y powers
diff(log10(xLimits));
set(gca,'Xlim',xLimits,'YLim',yLimits,... %# Set the limits and the
'DataAspectRatio',[1 logScale/powerScale 1]); %# data aspect ratio
set(gca,'XTick',[1e10 1e12 1e14 1e16]); %# Change the x axis tick marks
And here's the resulting plot:
Notice that the space between the 100 and 102 tick marks on the y axis spans the same number of pixels as the space between the 1010 and 1012 tick marks on the x axis, thus making a decade on one axis equal to a decade on the other.
If you don't want to change the axes limits, and instead want to use the default limits chosen by MATLAB, you can simply fetch the limits from the axes to perform the computations:
xLimits = get(hAxes,'XLim');
yLimits = get(hAxes,'YLim');
However, in order to disable MATLAB's automatic axes resizing behavior you will still have to either set the axes limits to the same values or set the limit mode properties to 'manual' when you update the 'DataAspectRatio' property:
set(gca,'Xlim',xLimits,'YLim',yLimits,...
'DataAspectRatio',[1 logScale/powerScale 1]);
%# OR...
set(gca,'XLimMode','manual','YLimMode','manual',...
'DataAspectRatio',[1 logScale/powerScale 1]);
If all of this seems like a lot of work, you can simplify things by putting it all into a function. I will actually be submitting a function decades_equal to the MathWorks File Exchange based on the code in this answer. For the time being, here is a trimmed down version (i.e. no error checking or help) that you can use:
function decades_equal(hAxes,xLimits,yLimits)
if (nargin < 2) || isempty(xLimits)
xLimits = get(hAxes,'XLim');
end
if (nargin < 3) || isempty(yLimits)
yLimits = get(hAxes,'YLim');
end
logScale = diff(yLimits)/diff(xLimits);
powerScale = diff(log10(yLimits))/diff(log10(xLimits));
set(hAxes,'Xlim',xLimits,...
'YLim',yLimits,...
'DataAspectRatio',[1 logScale/powerScale 1]);
end
And you can call the function as follows:
loglog(2.^[1:20]*1e10,(2.^[1:20]).^2); %# Plot your sample data
decades_equal(gca); %# Make the decades equal sizes
How it works...
You may be wondering what the logic is behind how I chose the scaling factors above. When trying to make the displayed size of a decade equal for each axes, we have to take into account both the number and sizes of decades within the axes ranges. In the above code, I am basically computing the average decade size for each axis, then using the ratios of the average decade sizes to scale the axes accordingly. For example, diff(yLimits) gives the total size of the y axis, and diff(log10(yLimits)) gives the number of decades (i.e. powers of ten) displayed on the y axis.
This may be easier to see if I reorder the operations in the above code like so:
yDecade = diff(yLimits)/diff(log10(yLimits)); %# Average y decade size
xDecade = diff(xLimits)/diff(log10(xLimits)); %# Average x decade size
set(gca,'XLim',xLimits,'YLim',yLimits,...
'DataAspectRatio',[1 yDecade/xDecade 1]);
And this will give the same scaling results as before.