Smooth data and graph in MATLAB [duplicate] - matlab

Using MATLAB, I have a matrix (data) and am plotting using imagesc(data) to produce a heatmap:
data = [1 1 1 1 1 1 1 1 1 1; 1 1.04 1.04 1.04 1.03 1 1.01 1.01 1.03 1.01; 1.36 1.3 1.25 1.2 1.15 1.1 1.2 1.13 1.07 1.11; 3.65 3.16 2.94 2.68 2.39 2.22 2.17 1.95 1.79 1.81; 5.91 5.75 5.47 5.3 4.98 4.79 4.62 4.55 4.38 4.19; 6 6 5.99 5.83 5.49 5.33 5.14 4.94 4.77 4.74];
imagesc(data)
Is there a way to 'smooth' the pixels in order to produce something more like this:

interp2 may be of use here. Use the data as key points, then create a finer grid of points that span the same width and height and interpolate in between the key points.
Something like this:
%// Define your data
data = [1 1 1 1 1 1 1 1 1 1; 1 1.04 1.04 1.04 1.03 1 1.01 1.01 1.03 1.01; 1.36 1.3 1.25 1.2 1.15 1.1 1.2 1.13 1.07 1.11; 3.65 3.16 2.94 2.68 2.39 2.22 2.17 1.95 1.79 1.81; 5.91 5.75 5.47 5.3 4.98 4.79 4.62 4.55 4.38 4.19; 6 6 5.99 5.83 5.49 5.33 5.14 4.94 4.77 4.74];
%// Define integer grid of coordinates for the above data
[X,Y] = meshgrid(1:size(data,2), 1:size(data,1));
%// Define a finer grid of points
[X2,Y2] = meshgrid(1:0.01:size(data,2), 1:0.01:size(data,1));
%// Interpolate the data and show the output
outData = interp2(X, Y, data, X2, Y2, 'linear');
imagesc(outData);
%// Cosmetic changes for the axes
set(gca, 'XTick', linspace(1,size(X2,2),size(X,2)));
set(gca, 'YTick', linspace(1,size(X2,1),size(X,1)));
set(gca, 'XTickLabel', 1:size(X,2));
set(gca, 'YTickLabel', 1:size(X,1));
%// Add colour bar
colorbar;
The code that's at the bottom is required because defining the finer grid ultimately increases the size of the image. I need to relabel the axes to go back to the original size.
We get this:
Small Note
I'm using MATLAB R2014a, and the default colour map is jet. You're using R2014b+ and the default colour map is parula. You won't get the same colour distribution as me, but you will get the smoothness you desire.

You can also use the pcolor(data) function with shading interp to make the color resolution smooth. No need to interpolate the data before plotting.

Related

Octave - why is surf not working but trisurf does?

I am able to plot a trisurf chart, but surf does not work.
What am I doing wrong?
pkg load statistics;
figure (1,'name','Matrix Map');
colormap('hot');
t = dlmread('C:\Map3D.csv');
tx =t(:,1);ty=t(:,2);tz=t(:,3);
tri = delaunay(tx,ty);
handle = surf(tx,ty,tz); #This does NOT work
#handle = trisurf(tri,tx,ty,tz); #This does work
`error: surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length
(X)
My data is in a CSV (commas not shown here)
1 2 -0.32
2 2 0.33
3 2 0.39
4 2 0.09
5 2 0.14
1 2.5 -0.19
2 2.5 0.13
3 2.5 0.15
4 2.5 0.24
5 2.5 0.33
1 3 0.06
2 3 0.44
3 3 0.36
4 3 0.45
5 3 0.51
1 3.5 0.72
2 3.5 0.79
3 3.5 0.98
4 3.5 0.47
5 3.5 0.55
1 4 0.61
2 4 0.13
3 4 0.44
4 4 0.47
5 4 0.58
1 4.5 0.85
surf error message is different in Matlab or in Octave.
Error message from Matlab:
Z must be a matrix, not a scalar or vector.
The problem is pretty clear here since you specified Z (for you tz) as a vector.
Error message from Octave:
surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)
You are wrong here since on your example, columns (Z) = 1, but length (X) = 26, so here is the mistake.
One of the consequences of that is that with surf you cannot have "holes" or undefined points on your grid. On your case you have a X-grid from 1 to 5 and a Y-grid from 2 to 4.5 but point of coordinate (2, 4.5) is not defined.
#Luis Mendo, Matlab and Octave do allow the prototype surf(matrix_x, matrix_y, matrix_z) but the third argument matrix_z still have to be a matrix (not a scalar or vector). Apparently, a matrix of only one line or column is not considered as a matrix.
To solve the issue, I suggest something like:
tx = 1:5; % tx is a vector of length 5
ty = 2:0.5:4.5; % ty is a vector of length 6
tz = [-0.32 0.33 0.39 0.09 0.14;
-0.19 0.13 0.15 0.24 0.33;
0.06 0.44 0.36 0.45 0.51;
0.72 0.79 0.98 0.47 0.55;
0.61 0.13 0.44 0.47 0.58;
0.85 0. 0. 0. 0.]; % tz is a matrix of size 6*5
surf(tx,ty,tz);
Note that I had to invent some values at the points where your grid was not defined, I put 0. but you can change it with the value you prefer.

Plot bar in matlab with log-scale x axis and same width

I want to plot a bar chart in Matlab with (1) log-scale for x-axis and (2)bars in same width. But with the code below, the width of the bars are different. Can any one help? Many thanks!
xdata = [0.01 0.018 0.032 0.056 0.1 0.18 0.32 0.56 1 1.8 3.2 5.6 10];
ydata = [1.3 1.6 1.5 1.2 1.0 3.5 0.6 3.1 1.6 1.9 1.7 0.3 0.4];
bar(xdata,ydata);
set(gca,'XScale','log');
Instead of plotting xdata on a log scale, plot the log of xdata on a linear scale. Then modify labels to reflect the linear value (not the used log value).
xdata = [0.01 0.018 0.032 0.056 0.1 0.18 0.32 0.56 1 1.8 3.2 5.6 10];
ydata = [1.3 1.6 1.5 1.2 1.0 3.5 0.6 3.1 1.6 1.9 1.7 0.3 0.4];
bar(log10(xdata),ydata);
set(gca,'Xtick',-3:1); %// adjust manually; values in log scale
set(gca,'Xticklabel',10.^get(gca,'Xtick')); %// use labels with linear values

How I can create a movie from a bunch of plots

I am really a beginner to make a movie. I need to make a movie from a bunch of plots. How I can make it.
I have 8 plots , which are y versus x. I want to make movie based on x to see how y change with increasing x.
Please consider my matlab file is as below:
x=[1 1.2 1.4 2 3 4 5 7 9 10];
y1=[2.8 7.6 10.9 12.3 15.0 21 12.3 14.5 42.4 47.7];
y2=1e8.*[0.599e-7 0.607e-7 0.343e-7 0.3e-7 0.873e-8 0.578e-8 0.298e-8 0.725e-9 0.14e-8 0.478e-9];
y3=10.*[0.136 0.544 0.834 1.03 0.366 0.314 0.703 0.207 0.696 0.164];
y4=10.*[0.26 0.21 0.17 0.25 0.31 0.34 0.16 0.15 0.13 0.31];
y5=....
y6=...
y7=...
y8=[6 7.6 10.9 12.3 15.0 21 12.3 19.5 42.4 47.7 ];
plot(x,y1)
hold on
plot(x,y2)
hold on
plot(x,y3)
hold on
plot(x,y4)
hold on
plot(x,y5)
hold on
plot(x,y6)
hold on
...
plot(x,y8)
I wrote following as a simple example but it does not work:
clc;clear all;
x=[1 1.2 1.4 2 3 4 5 7 9 10];
y = zeros(4,10);
y(1,:)=[2.8 7.6 10.9 12.3 15.0 21 12.3 14.5 42.4 47.7 ];
y(2,:)=1e8.*[0.599e-7 0.607e-7 0.343e-7 0.3e-7 0.873e-8 0.578e-8 0.298e-8 0.725e-9 0.14e-8 0.478e-9];
y(3,:)=10.*[0.136 0.544 0.834 1.03 0.366 0.314 0.703 0.207 0.696 0.164 ];
y(4,:)=10.*[0.26 0.21 0.17 0.25 0.31 0.34 0.16 0.15 0.13 0.31 ];
figure;
hold on
for n = 1:10
plot(x,y)
M(n)=getframe; % get frame from the current figure;
end
movie(M,10); %plays movie M 10 times
In a nut shell , How I can make a movie like Fig. 3.2: in the following link
The basic code for making a movie from a given figure is like this:
figure;
hold on
for n = 1:20
plot(1:10,n*(1:10))
M(n)=getframe; % get frame from the current figure;
end
movie(M,10); %plays movie M 10 times
Look into the help files for getframe and movie to see what other options are available. To save a movie out, see movie2avi.
Note that for a given figure you only need to call hold on once. If all your y values are of the same length, then you can re-write your code/plotting more efficiently like this:
x=[1 1.2 1.4 2 3 4 5 7 9 10];
y = zeros(8,10);
% then this for each of your sets of y values
y(1,:) = [2.8 7.6 10.9 12.3 15.0 21 12.3 14.5 42.4 47.7 53 81.3 86.1];
...
y(8,:)=[6 7.6 10.9 12.3 15.0 21 12.3 19.5 42.4 47.7 53 81.3 86.1 ];
plot(x,y) % plots all the y's against x with automatic coloring
plot(x,y(n,:)) % plots just one set of y values against x

scale part of an axis in matlab

I have the following image which I want to have the depth axis range like below :
(10 9.5 9 8.5 8 7.5 7 6 5 3 2 1 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 0) to show the data between depth 1 and 0 in larger scale, and I have the following code
depths = [10 5 1 0.5 0; 10 5 1 0.5 0] % these are the real depths in meter
contourf(points,depths,RFU15102013_BloomAsMainPoint);
set(gca, 'XTick', points(1) : points(2), 'XTickLabel',{ 'LSB1', 'LSB2'});
ylabel('Depth(m)');
xlabel('Points');
title('Date: 15.10.2013');
this is the image :
how can I do that?
EDIT1
Real Data:
RFU15102013_BloomAsMainPoint = [ 2.71 1.23 1.30 1.20 14.37 ; 2.51 1.36 1.01 1.24 1.15];
points = [1 1 1 1 1; 2 2 2 2 2 ];
depths = [10 5 1 0.5 0; 10 5 1 0.5 0];
As most of a data changes around zero it could be enough to change scaling of Y axis. Here is an example
close all; clear all;
z = [ 2.71 1.23 1.30 1.20 14.37 ; 2.51 1.36 1.01 1.24 1.15];
x = repmat([1; 2], 1, 5);
y = repmat([10 5 1 0.5 0], 2, 1);
% plotting with equally spaced y-s
h = subplot(1,2,1);
contourf(x,y,z);
y2 = log(y + 0.25);
yTicks = linspace(min(y2(1,:)), max(y2(1,:)), 10);
% plotting with logarithmically spaced y-s
h = subplot(1,2,2)
contourf(x,y2,z);
set(h,'YTick', yTicks)
set(h,'YTickLabel', exp(yTicks) - 0.25);
print('-dpng','scaling.png')
The result
This way any monotonic continuous function for axis scaling can be applied.
You could use UIMAGE - UIMAGESC from the mathworks file exchange and set the y values to emphaisize points in 1 to 0 range.

Selecting elements from a matrix in matlab

I have a matrix which is 36 x 2, but I want to seperate the elements to give me 18, 2 x 2 matrices from top to bottom. E.g. if I have a matrix:
1 2
3 4
5 6
7 8
9 10
11 12
13 14
... ...
I want to split it into seperate matrices:
M1 = 1 2
3 4
M2 = 5 6
7 8
M3 = 9 10
11 12
..etc.
maybe the following sample code could useful:
a=rand(36,2);
b=reshape(a,2,2,18)
then with the 3rd index of b you can access your 18 2x2 matrices, eg. b(:,:,2) gives the second 2x2 matrix.
I think that the direct answer to your question is:
sampledata = [...
0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.10 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 1.01 1.02 1.03 1.04 1.05 1.06 1.07 1.08 1.09 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18; ...
0.19 0.20 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.30 0.31 0.32 0.33 0.34 0.35 0.36 1.19 1.20 1.21 1.22 1.23 1.24 1.25 1.26 1.27 1.28 1.29 1.30 1.31 1.32 1.33 1.34 1.35 1.36];
for ix = 1:(size(sampledata,2)/2)
assignin('base',['M' sprintf('%02d',ix)], sampledata(:,ix*2+[-1 0]))
end
This creates 18 variables, named 'M01' through 'M18', with pieces of the sampledata matrix.
However, please don't use dynamic variable names like this. It will complicate every other piece of code that it touches. Use a cell array, a 3D array (as suggested by #Johannes_Endres +1 BTW), or structure. Anything that removes the need for you to write something like this later on:
%PLEASE DO NOT USE THIS
%ALSO DO NOT BACK YOURSELF INTO A CORNER WHERE YOU HAVE TO DO IT IN THE FUTURE
varNames = who('M*');
for ix = 1:length(varNames )
str = ['result(' num2str(ix) ') = some_function(' varNames {ix} ');'];
eval(str);
end
I've seen code like this, and it is slow and extremely cumbersome to maintain, not to mention the headache and pain to your internal beauty-meter.
x = reshape(1:36*2,[2 36])'
k = 1
for i = 1:2:35
eval(sprintf('M%d = x(%d:%d,:);',k,i,i+1));
k = k+1;
end