How to include Annotate extends ... in this MATLAB findpeaks? - matlab

I have minimums and maximums in the output now (Fig.1) but I would like to get labels (Fig. 2) for sorted maximums (tallest get 1, ...) and similarly for minimums (lowest gets 1).
I can do the output of Fig. 1 by the following but I cannot integrate those annotations to the function
close all; clear all; clc;
% https://se.mathworks.com/help/signal/ref/findpeaks.html
% http://stackoverflow.com/a/26837689/54964
x = linspace(0,1,1000);
Pos = [1 2 3 5 7 8]/10;
Hgt = [4 4 2 2 2 3];
Wdt = [3 8 4 3 4 6]/100;
for n = 1:length(Pos)
Gauss(n,:) = Hgt(n)*exp(-((x - Pos(n))/Wdt(n)).^2);
end
PeakSig = sum(Gauss) - exp(sum(Gauss))/10;
plot(x, PeakSig);
hold on;
[p l]=findpeaks(PeakSig); %,x); %,'Annotate','extents','WidthReference','halfheight')
plot(x(l), p, 'ko', 'MarkerFaceColor', 'g');
[pn ln]=findpeaks(-PeakSig); %,x); %,'Annotate','extents','WidthReference','halfheight')
plot(x(ln), -pn, 'ko', 'MarkerFaceColor', 'r');
title('Signal Peak Widths')
To just append 'Annotate','extents','WidthReference','halfheight') to [p l]=findpeaks(...) is not working in the application etc the following apparently because the proceeding line plot(x(l), p, 'ko', 'MarkerFaceColor', 'g'); does not understand the extra content made by the one-liner in the corresponding variables
[p l]=findpeaks(PeakSig,'Annotate','extents','WidthReference','halfheight')
[p l]=findpeaks(PeakSig, x, 'Annotate','extents','WidthReference','halfheight')
Fig. 1 Current output without those annotations,
Fig. 2 Expected output but with notes of maximums and minimums
MATLAB: 2016b
OS: Debian 8.5 64 bit
Hardware: Asus Zenbook UX303UA

Here is one way to to this:
x = linspace(0,1,1000);
Pos = [1 2 3 5 7 8]/10;
Hgt = [4 4 2 2 2 3];
Wdt = [3 8 4 3 4 6]/100;
Gauss = zeros(numel(Pos),numel(x));
for n = 1:numel(Pos)
Gauss(n,:) = Hgt(n)*exp(-((x - Pos(n))/Wdt(n)).^2);
end
PeakSig = sum(Gauss) - exp(sum(Gauss))/10;
% get the peaks:
[p,xmax] = findpeaks(PeakSig,x);
maxsrt = sortrows([xmax;p].',-2);
[pn,xmin] = findpeaks(-PeakSig,x);
minsrt = sortrows([xmin;-pn].',2);
% plotting:
blue = [0 0.447 0.741];
plot(x,PeakSig,xmax,p+0.2,'v','MarkerFaceColor',blue,'MarkerEdgeColor',blue);
% you can comment the line above and uncomment the line below, if you
% prefer:
% findpeaks(PeakSig,x,'Annotate','peaks');
text(maxsrt(:,1),maxsrt(:,2)+0.2,num2str((1:numel(p)).'),'FontSize',14,...
'VerticalAlignment','bottom','HorizontalAlignment','center')
ylim([-10 3]);
grid on
hold on
plot(xmin,-pn-0.2,'^','MarkerFaceColor',blue,'MarkerEdgeColor',blue);
hold off
text(minsrt(:,1),minsrt(:,2)-0.2,num2str((1:numel(pn)).'),'FontSize',14,...
'VerticalAlignment','top','HorizontalAlignment','center')
title('Signal Peak Widths')

And here is another way to do this, using gscatter. Instead of calling plot twice (and maybe more if other annotations are needed), you concat all the positions (x-y) and type of annotations to one array (pks bellow), and plot them all at once by thier type (i.e. group) with gscatter:
x = linspace(0,1,1000);
Pos = [1 2 3 5 7 8]/10;
Hgt = [4 4 2 2 2 3];
Wdt = [3 8 4 3 4 6]/100;
Gauss = zeros(numel(Pos),numel(x));
for n = 1:numel(Pos)
Gauss(n,:) = Hgt(n)*exp(-((x - Pos(n))/Wdt(n)).^2);
end
PeakSig = sum(Gauss) - exp(sum(Gauss))/10;
% get the peaks:
[p,xmax] = findpeaks(PeakSig,x);
maxsrt = sortrows([xmax;p].',-2);
[pn,xmin] = findpeaks(-PeakSig,x);
minsrt = sortrows([xmin;-pn].',2);
% plotting:
pks = [[xmin xmax];[-pn-0.2 p+0.2];[zeros(1,numel(pn)) ones(1,numel(p))]].';
blue = [0 0.447 0.741];
ax = axes;
plot(ax,x,PeakSig)
hold on
gscatter(pks(:,1),pks(:,2),pks(:,3),blue,'^v')
hold off
ax.Children(1).MarkerFaceColor = blue;
ax.Children(2).MarkerFaceColor = blue;
text(maxsrt(:,1),maxsrt(:,2)+0.2,num2str((1:numel(p)).'),'FontSize',14,...
'VerticalAlignment','bottom','HorizontalAlignment','center')
text(minsrt(:,1),minsrt(:,2)-0.2,num2str((1:numel(pn)).'),'FontSize',14,...
'VerticalAlignment','top','HorizontalAlignment','center')
ylim([-10 3]);
legend off
grid on
title('Signal Peak Widths')
the result is exactly the same, but this is more short and maybe more elegant.

Related

Determine accuracy of a model in matlab

I am currently trying to make some plot showing that GMM is better at modeling data than MNN (multi model normal distribution), but can't make a plot in which both fits are in. Here is my current code:
MU1 = [1 2];
SIGMA1 = [2 0; 0 .5];
MU2 = [4 6];
SIGMA2 = [1 0; 0 1];
rng(1); % For reproducibility
X = [mvnrnd(MU1,SIGMA1,1000);
mvnrnd(MU2,SIGMA2,1000)];
figure;
scatter(X(:,1),X(:,2),10,'.')
options = statset('Display','final');
gm = fitgmdist(X,2,'Options',options); % GMM fit
G = fitgmdist(X,1) % fit MNN - only 1 component are being used
gmPDF = #(x,y)pdf(gm,[x y]);
F = #(x,y) pdf(G,[x y])
hold on
%h = ezcontour(gmPDF,[-3 10],[-3 10]);
d = ezcontour(F,[-3 10],[-3 10]);
title('Scatter Plot and PDF Contour')
hold off
%%
close all
I am able to see the plots, but can i somehow print the accuracy of both?
Something like number of outliers or something else?

how to add data labels for bar graph in matlab

For example (code):
x = [3 6 2 9 5 1];
bar(x)
for this I need to add data labels on top of the each bar.
I know that I have to use TEXT keyword, but I'm not getting how to implement it.
Here is a simple solution with text:
x = [3 6 2 9 5 1];
bar(x)
ylim([0 max(x)*1.2])
text(1:numel(x),x+0.5,num2cell(x))
Based off this answer:
data = [3 6 2 9 5 1];
figure; %// Create new figure
hbar = bar(data); %// Create bar plot
%// Get the data for all the bars that were plotted
x = get(hbar,'XData');
y = get(hbar,'YData');
ygap = 0.1; %// Specify vertical gap between the bar and label
ylimits = get(gca,'YLim');
%// The following two lines have minor tweaks from the original answer
set(gca,'YLim',[ylimits(1),ylimits(2)+0.2*max(y)]);
labels = cellstr(num2str(data')) %//'
for i = 1:length(x) %// Loop over each bar
xpos = x(i); %// Set x position for the text label
ypos = y(i) + ygap; %// Set y position, including gap
htext = text(xpos,ypos,labels{i}); %// Add text label
set(htext,'VerticalAlignment','bottom', 'HorizontalAlignment','center')
end
After some attempts I have found the solution. Do the following:
y = Data;
for b = 1 : 10
BarPlot(b) = bar(b, y(b), 'BarWidth', 0.9); % actual plot
set(BarPlot(b), 'FaceColor', 'blue'); %Apply color
barTopper = sprintf('%.1f%s', y(b)*100,'%'); % Place text on top
text(b-0.5, y(b)+0.01, barTopper, 'FontSize', barFontSize); % position the text
hold on;
end
Let me know if it works.

Position a matlab figure generated in a GUI for automatic save

I've been having some issues automatically saving a figure plotted in a GUI axes panel. Here's the code I have so far:
x= [1 2 3 4 5 6 7 8 9 10];
y = [10 5 6 7 8 20 5 4 3 8];
p = polyfit(x, y, 6);
r = polyval(p, x);
xlabel(handles.axes1, 'Time (\mus)');
ylabel(handles.axes1, 'Angular Velocity (rad/s)');
title(handles.axes1, 'Angular Velocity vs. Time (kT Test)');
aV = plot(handles.axes1, x, y, x, r, 'g--');
%Save figure
ftmp = figure();
copyobj(handles.axes1, ftmp);
set(ftmp, 'units', 'normalized', 'outerposition', [0 0 1 1]);
%Create file name
fileName = ['Test' num2str(time(1)) '_' num2str(time(2)) '_' num2str(time(3))]
saveas(ftmp, fileName, 'png');
The image is automatically saved, but it doesn't come out right. For instance, here is what the saved image looks like:
As you can see, the image is quite skewed. However, if I manually save the image, the entire figure is centered and saved. Is there a way to reposition the figure while automatically saving?
(Please note that I'm looking for a solution that does not use export_fig).
I've searched this sight for a while, and none of the answers to similar questions have offered a solution to my problem.
Any constructive advice is appreciated.
Here is what I would do:
x= [1 2 3 4 5 6 7 8 9 10];
y = [10 5 6 7 8 20 5 4 3 8];
p = polyfit(x, y, 6);
r = polyval(p, x);
figure(1);
clf();
plot(x, y, x, r, 'g--');
xlabel('Time (\mus)');
ylabel('Angular Velocity (rad/s)');
title('Angular Velocity vs. Time (kT Test)');
time = clock();
fileName = ['Test' num2str(time(1)) '_' num2str(time(2)) '_' num2str(time(3))]
print('-f1','-dpng', fileName);
Not sure exactly what you want for your filename, so just made that up as I went. The time=clock() is not needed if you want to have a different filename.
Note, too, that you can use saveas(1, fileName, 'png'); as the last line.

generate rectangle annotation in the current figure

I would like to insert a rectangle into my matlab figure to highlight a specific region:
x = [0 1 2 2 3 4 5 6 7 8 9 10];
y = [0 1 2 4 3 4 5 6 7 8 9 10];
fh = figure(1);
plot(x,y)
xlim([0 10]);
ylim([0 10]);
I can do this by using the annotation function and defining the left bottom width height of the rectangle.
I am wondering, however, can this be done according to the x and y values from the figure in question? For the example shown, for example I would like to draw a rectangle from x = 1.5 y = 1.5 with a height of 3 and a width of two. This is my attempt:
% define location of lbwh in terms of x and y values
l = 1.5;
b = 1.5;
w = 2;
h = 3;
% convert factor of 1
xx = xlim;
l = l./xx(2);
b = b./xx(2);
w = w./xx(2);
h = h./xx(2);
annotation('rectangle','position',[l,b,w,h]);
The problem is that the position I'm providing is in terms of the (0,0) position in the plot and not the bottom left hand of the figure window. how can I correct this?
One way would be to just create a rectangle from line graphs:
plot([l,l,l+w,l+w,l],[b,b+h,b+h,b,b], 'r', 'LineWidth', 2)

How to plot 3D grid (cube) in Matlab

Hi I would like to plot transparent cube-shaped grid with lines in it. Something like this:
However, I managed only to draw a 2D grid:
[X,Y] = meshgrid(-8:.5:8);
Z = X+1;
surf(X,Y,Z)
I use Matlab R2009b.
If it is impossible to plot this in matlab could you recommend me a software I could use.
Consider this vectorized solution. It has the advantage that it creates a single graphic object:
%# these don't all have to be the same
x = -8:2:8; y = -8:2:8; z = -8:2:8;
[X1 Y1 Z1] = meshgrid(x([1 end]),y,z);
X1 = permute(X1,[2 1 3]); Y1 = permute(Y1,[2 1 3]); Z1 = permute(Z1,[2 1 3]);
X1(end+1,:,:) = NaN; Y1(end+1,:,:) = NaN; Z1(end+1,:,:) = NaN;
[X2 Y2 Z2] = meshgrid(x,y([1 end]),z);
X2(end+1,:,:) = NaN; Y2(end+1,:,:) = NaN; Z2(end+1,:,:) = NaN;
[X3 Y3 Z3] = meshgrid(x,y,z([1 end]));
X3 = permute(X3,[3 1 2]); Y3 = permute(Y3,[3 1 2]); Z3 = permute(Z3,[3 1 2]);
X3(end+1,:,:) = NaN; Y3(end+1,:,:) = NaN; Z3(end+1,:,:) = NaN;
%#figure('Renderer','opengl')
h = line([X1(:);X2(:);X3(:)], [Y1(:);Y2(:);Y3(:)], [Z1(:);Z2(:);Z3(:)]);
set(h, 'Color',[0.5 0.5 1], 'LineWidth',1, 'LineStyle','-')
%#set(gca, 'Box','on', 'LineWidth',2, 'XTick',x, 'YTick',y, 'ZTick',z, ...
%# 'XLim',[x(1) x(end)], 'YLim',[y(1) y(end)], 'ZLim',[z(1) z(end)])
%#xlabel x, ylabel y, zlabel z
axis off
view(3), axis vis3d
camproj perspective, rotate3d on
If you don't mind a few for loops, something like this will work:
clf
figure(1)
for g = 0:.2:2
for i = 0:.2:2
plot3([g g], [0 2], [i, i])
hold on
end
end
for g = 0:.2:2
for i = 0:.2:2
plot3([0 2], [g g], [i, i])
hold on
end
end
for g = 0:.2:2
for i = 0:.2:2
plot3([i i], [g g], [0 2])
hold on
end
end
You will just need to make the grid transparent by probably changing line properties, I don't think you can change alpha values to accomplish this. Hope that is helpful.
A more vectorized version of Stephen's answer might be the following:
i = 0:0.2:2;
[X Y] = meshgrid(i,i);
x = [X(:) X(:)]';
y = [Y(:) Y(:)]';
z = [repmat(i(1),1,length(x)); repmat(i(end),1,length(x))];
col = 'b';
hold on;
plot3(x,y,z,col);
plot3(y,z,x,col);
plot3(z,x,y,col);
Unfortunately, MATLAB does not currently support transparent lines (to my knowledge). If you really need them to be transparent I'd suggest using 'patch'.
I understand this is a late reply but it is still valid in case anyone else is looking at doing the same thing.
Assuming you are plotting cubes (/their edges), an alternative to the answers already provided is to use the 'plotcube' code from Oliver:
plotcube
The advantage of this solution is that you can:
Change the transparency of the faces (FaceAlpha), and/or,
Change the transparency of the edges (EdgeAlpha), and/or,
Change the colour of the lines (EdgeColor).
All of these can be constants, or variables.
(e.g. fixed edge colour, or a colour that changes with Z-value etc.)
To add in functionality of 2. and 3. (above) change the 'cellfun(#patch...' section in Olivers code, adding in the four extra lines of code as follows: (replace the whole cellfun section with this; including the new 'EdgeAlpha' and 'EdgeColor' lines):
cellfun(#patch,XYZ{1},XYZ{2},XYZ{3},...
repmat({clr},6,1),...
repmat({'FaceAlpha'},6,1),...
repmat({alpha},6,1),...
repmat({'EdgeAlpha'},6,1),...
repmat({0.2},6,1),... % Set this value to whatever you want; even a variable / matrix
repmat({'EdgeColor'},6,1),...
repmat({'black'},6,1)...
);
For more info on 'patch' please see patch documentation.
An important note:
- for large models (many cubes) this is very slow to run.
e.g. running this 'plotcube' function in a 'for' loop in MATLAB over thousands of blocks. I believe this is from calling the 'patch' function multiple times.
A better solution would be to vectorise; to put all your points (vertices/faces/whatever) together in a single matrix first and then call the #patch function only once (no 'for' loop). This would require changing the code somehow to update all the XYZ data.
I hope that helps someone.
Here is the 'plotcube' code in case the link to the original code by Oliver breaks someday:
function plotcube(varargin)
% PLOTCUBE - Display a 3D-cube in the current axes
%
% PLOTCUBE(EDGES,ORIGIN,ALPHA,COLOR) displays a 3D-cube in the current axes
% with the following properties:
% * EDGES : 3-elements vector that defines the length of cube edges
% * ORIGIN: 3-elements vector that defines the start point of the cube
% * ALPHA : scalar that defines the transparency of the cube faces (from 0
% to 1)
% * COLOR : 3-elements vector that defines the faces color of the cube
%
% Example:
% >> plotcube([5 5 5],[ 2 2 2],.8,[1 0 0]);
% >> plotcube([5 5 5],[10 10 10],.8,[0 1 0]);
% >> plotcube([5 5 5],[20 20 20],.8,[0 0 1]);
% Default input arguments
inArgs = { ...
[10 56 100] , ... % Default edge sizes (x,y and z)
[10 10 10] , ... % Default coordinates of the origin point of the cube
.7 , ... % Default alpha value for the cube's faces
[1 0 0] ... % Default Color for the cube
};
% Replace default input arguments by input values
inArgs(1:nargin) = varargin;
% Create all variables
[edges,origin,alpha,clr] = deal(inArgs{:});
XYZ = { ...
[0 0 0 0] [0 0 1 1] [0 1 1 0] ; ...
[1 1 1 1] [0 0 1 1] [0 1 1 0] ; ...
[0 1 1 0] [0 0 0 0] [0 0 1 1] ; ...
[0 1 1 0] [1 1 1 1] [0 0 1 1] ; ...
[0 1 1 0] [0 0 1 1] [0 0 0 0] ; ...
[0 1 1 0] [0 0 1 1] [1 1 1 1] ...
};
XYZ = mat2cell(...
cellfun( #(x,y,z) x*y+z , ...
XYZ , ...
repmat(mat2cell(edges,1,[1 1 1]),6,1) , ...
repmat(mat2cell(origin,1,[1 1 1]),6,1) , ...
'UniformOutput',false), ...
6,[1 1 1]);
cellfun(#patch,XYZ{1},XYZ{2},XYZ{3},...
repmat({clr},6,1),...
repmat({'FaceAlpha'},6,1),...
repmat({alpha},6,1)...
);
view(3);
you can make the inside line kind of transparent by setting color = [0.65, 0.65, 0.65]. And you can use dash line style for interior lines and solid lines for boundary to make it more like a 3-D object.
In my software package, I code a mesh3 function to plot the 3-D tensor product meshes.
clear all
close all
clc
Nx=11;
Ny=11;
Nz=11;
clf
hold on
[i,j]=meshgrid(1:Nx,1:Ny);
k=zeros(Ny,Nx)+Nz;
surf(i,j,k)
[i,k]=meshgrid(1:Nx,1:Nz);
j=zeros(Nz,Nx)+Ny;
surf(i,j,k)
[j,k]=meshgrid(1:Ny,1:Nz);
i=zeros(Nz,Ny)+Nx;
surf(i,j,k)
[i,j]=meshgrid(1:Nx,1:Ny);
k=zeros(Ny,Nx)+1;
surf(i,j,k)
[i,k]=meshgrid(1:Nx,1:Nz);
j=zeros(Nz,Nx)+1;
surf(i,j,k)
[j,k]=meshgrid(1:Ny,1:Nz);
i=zeros(Nz,Ny)+1;
surf(i,j,k)
view(30,30)