Plot bode inside UI axes of Matlab's app designer - matlab

I am creating a UI on app designer and I want to plot a bode in my UI.axes.
This figure contains two plots (magnitude, phase) and what I want to do is to plot each plot in different ui.axes.
I've managed to plot only the magnitude bode and the phase bode using the following code :
clc;
clear all;
num = [2];
den = [conv([1 1], conv([1 1], [1 1]))];
sys = tf(num, den);
[mag, phase, freq] = bode(sys, {0.1, 100});
bodemag(sys, freq)
h = bodeplot(sys, freq);
setoptions(h,'MagVisible','off');
This code gives me these two seperate plots :
I am trying to insert these plots in two different ui axes in my app.
Does any one have an idea or another approach on how to insert the plots ?
NB : I've tried the following :-
Writing the code direcly into the app designer but it creates a pop up instead
Using the plot(app.UiAxes, ...., ....) function but I can't seem to make it work

Can you show your code from appdesigner with the app.UIAxes.
Which Matlab realease do you use ?
As i know subplots are not supported in a UIAxes in older versions. So you have to make two UIAxes or use newer version.
If you write your code directly to appdesigner you are creating an Axes. There is an difference between UIAxes and Axes object. If you want to use Axes you have to set more properties to make it display inside your UIFigure of your App.
You tried this ?
I don't know if the UIAxes supports bodemag function. This could make sense, if it doesn't work with UIAxes.
bode = bodemag(app.UIAxes,sys, freq);
If UIAxes doesn't support bodemag then you have to do it with normal axes and code the positioning of this axes.
This is a good example how to do it.: https://de.mathworks.com/help/matlab/creating_guis/polar-plotting-app-gui-in-app-designer.html
And this is the part that is required additional.
% Create polar axes and position it in pixels
app.Pax = polaraxes(app.UIFigure);
app.Pax.Units = 'pixels';
app.Pax.Position = [260 55 230 230];

Related

Matlab call subplot with multiple volshow 3d images

I am attempting to plot two volumetric reconstructions created with MATLAB's volshow function.
I've tried calling subplot like I would with a plot but the second volshow object overwrites the first volshow object in the figure.
here's a code snippet that recreates the problem
vol1 = rand([10 10 10]);
vol2 = rand([10 10 10]);
subplot(1,2,1)
volshow(vol1);
subplot(1,2,2)
volshow(vol2);
How do I get both images to display simultaneously on the same figure?
I don't have access to the image processing toolbox so I can't test this.
The online help for volshow that you link only lists figure and uipanel objects as possible parents.
So I would try:
f = figure;
p1 = uipanel(f,'Position',[0,0,0.5,1]);
p2 = uipanel(f,'Position',[0.5,0,0.5,1]);
volshow(vol1, 'Parent',p1);
volshow(vol2, 'Parent',p2);

GCA function doen't work to change axis-labels

I try to present 8 (name) labels on my x-axis. Instead, I get number 1 to 8.
Problem: In my previous asked question, I used gca function, that allows me to change axis labels. However, the same gca function doesn't work here.
This is my MatLab output:
Instead of 1,...8, I want to see Firm1...Firm8!
This is my code:
figure(2);
%four variables:
%pi --> 8x1 vector
%E_R_BL_Idzorek --> 8x1 vector
%pi_star1 --> 8x1 vector
%ER_100_TF1 --> 8x1 vector
ALL_DATA=[pi(1,1) E_R_BL_Idzorek(1,1) pi_star1(1,1) ER_100_TF1(1,1);pi(2,1) E_R_BL_Idzorek(2,1) pi_star1(2,1) ER_100_TF1(2,1);pi(3,1) E_R_BL_Idzorek(3,1) pi_star1(3,1) ER_100_TF1(3,1);pi(4,1) E_R_BL_Idzorek(4,1) pi_star1(4,1) ER_100_TF1(4,1);pi(5,1) E_R_BL_Idzorek(5,1) pi_star1(5,1) ER_100_TF1(5,1);pi(6,1) E_R_BL_Idzorek(6,1) pi_star1(6,1) ER_100_TF1(6,1);pi(7,1) E_R_BL_Idzorek(7,1) pi_star1(7,1) ER_100_TF1(7,1);pi(8,1) E_R_BL_Idzorek(8,1) pi_star1(8,1),ER_100_TF1(8,1)];
%plotting it with a bar function
bar(ALL_DATA);
%This is where I have problem with gca function
set(gca,'xticklabel',{'Firm1','Firm2','Firm3','Firm4','Firm5','Firm6','Firm7','Firm8'});
%this is the grid part:
grid on
ll = cell(1,4);
ll{1}='pi'; ll{2}='ERidz'; ll{3}='piTF'; ll{4}='ERTF';
legend(bar(ALL_DATA),ll);
You are using a newer version of MATLAB so you should use the newer graphics system. The newer system is based on objects. This makes setting properties of things like axes easier. For example:
fh = figure; % creates the figure window save the figure handle to set it's properties
ax = axes(fh); % creates the axes in the figure, again save the object
x = rand(8,100);
h = bar(ax, x); % create the bar graph in your axes object
% now use the saved object to access the exact feature you want. This way you always have the thing you want. No searching.
ax.XTickLabel = {'Firm1','Firm2','Firm3','Firm4','Firm5','Firm6','Firm7','Firm8'};
Saving the objects is also handy for tracking legends and other things. For example: legend(ax,... You know exactly which legend you're dealing with.
What appears to be happening is that you are correctly changing the XTicks as you want but then you overwrite your graph with legend(bar(.... That creates a new bar graph. Try changing that line to just legend(ll). I would still suggest using the object system.
It seems the problem is that you redraw the bar when you run
legend(bar(ALL_DATA),ll);
You should simply do
legend(ll);

Plot within a plot in MATLAB

I am trying to create a smaller plot within a plot in MATLAB, for example like the image of this MATLAB File Exchange Upload.
There, two figures are created and then both of them are plotted in one figure.
My problem however is that I already have two MATLAB figures from earlier simulations and I need to embed one figure into the other one, i.e., one would be small and the other plot would be big but in the same graph. Could someone suggest an easy way to do this?
This can be done using the copyobj function. You'll need to copy the Axes object from one figure to the other:
f(1) = openfig('fig1.fig');
f(2) = openfig('fig2.fig');
ax(1) = get(f(1),'CurrentAxes'); % Save first axes handle
ax(2) = copyobj(get(f(2),'CurrentAxes'),f(1)); % Copy axes and save handle
Then you can move and resize both axes as you like, e.g.
set(ax(2),'Position', [0.6, 0.6, 0.2, 0.2]);

Match legend to axes objects

Context:
I have a (programmatic) GUI which contains several axes objects inside some uipanel parenting structure. Some of these axes have legend objects associated, some don't.
I want to include a button in my GUI which copies the currently visible plot into a new figure including its legend if it has one.
I know how to get the handles to the currently visible uipanel and all axes objects inside it. I also know how to tell the axes apart from the legends.
Question:
How can I match the legends to the axes?
For example, in one case my GUI shows 2 axes with some plots, each of which has its own legend. When I click the 'export' button, I want 2 new figures to be created, each containing one axes with its corresponding legend.
What I'm currently able to do is
put everything in one figure (they overlap in that case because their positions in the original uipanels are the same),
put each axes and each legend into their own respective figures,
put all axes in one and all legends in another figure and
put all axes in their own figure with all legends within the same panel.
split it up by panel, that is, put all subplots into the same figure and each group of plots in their own figure.
Problem:
The problem is, I don't have the handles to either of those objects. I only have the handles to the uipanel objects. The graphics inside the panels are built by another function which contains all sorts of tricky stuff, but doesn't return handles. Also the parenting structure of said panels makes it rather hard to do this with tricks like get(handles.panels{1},'Children') because it will work in some, but not all cases.
I thought about simply exporting the panels (and have actually a working version which does this), but this has several problems, mainly related to figure tools and resizing. I want to get rid of the panels when I use the "Export" button.
Code Snippet / Example:
The following code snippet will create an example GUI with access to all handles I have access to in my complete GUI. Clicking the buttons will show the different versions I got to "work". What I want is one figure for each axes including its legend, if it has one. the 4th version (same parent) comes close, but breaks if it encounters subplots, the 5th version (by panel) simply puts entire subplot groups into one window (in which case, at least, they don't overlap). Copy the code into a new .mfile to try it.
function test
figure(1)
clf
t=(0:0.1:10)'; %'// dummy comment
p2 = uipanel('Visible','off','Position',[0 0 1 1]);
p1 = uipanel('position',[0 0 1 1]);
p11 = uipanel('Parent',p1,'Position',[0 0 0.5 0.9]);
p12 = uipanel('Parent',p1,'Position',[0.5 0 0.5 0.9]);
uicontrol('Style','push','String','all in one','Units','norm',...
'Position',[0.05 0.91 0.14 0.06],'Callback',#export1);
uicontrol('Style','push','String','all in own','Units','norm',...
'Position',[0.24 0.91 0.14 0.06],'Callback',#export2);
uicontrol('Style','push','String','by type','Units','norm',...
'Position',[0.43 0.91 0.14 0.06],'Callback',#export3);
uicontrol('Style','push','String','same parent','Units','norm',...
'Position',[0.62 0.91 0.14 0.06],'Callback',#export4);
uicontrol('Style','push','String','same panel','Units','norm',...
'Position',[0.81 0.91 0.14 0.06],'Callback',#export5);
subplot(1,1,1,'Parent',p11)
plot(t,[sin(t) cos(t)])
legend('Sine','Cosine')
subplot(2,1,1,'Parent',p12)
plot(t,[polyval([0.05 -1 2],t) exp(-t) abs(t-3)])
subplot(2,1,2,'Parent',p12)
plot(t,erf(t))
legend('Error function')
function export1(~,~)
current = findobj('Type','uipanel','Parent',1,'Visible','on');
visible_axes = findobj(current,'Type','axes');
copyobj(visible_axes,figure);
end
function export2(~,~)
current = findobj('Type','uipanel','Parent',1,'Visible','on');
visible_axes = findobj(current,'Type','axes');
for i=1:length(visible_axes)
copyobj(visible_axes(i),figure);
end
end
function export3(~,~)
current = findobj('Type','uipanel','Parent',1,'Visible','on');
visible_axes = findobj(current,'Type','axes','Tag','');
visible_legends = findobj(current,'Tag','legend');
copyobj(visible_axes,figure);
copyobj(visible_legends,figure);
end
function export4(~,~)
current = findobj('Type','uipanel','Parent',1,'Visible','on');
visible_axes = findobj(current,'Type','axes','Tag','');
visible_legends = findobj(current,'Tag','legend');
for i=1:length(visible_axes)
par = get(visible_axes(i),'Parent');
same = findobj(visible_legends,'Parent',par);
h=figure;
copyobj(visible_axes(i),h)
copyobj(same,h)
end
end
function export5(~,~)
current = findobj('Type','uipanel','Parent',1,'Visible','on');
visible_axes = findobj(current,'Type','axes');
parents = cell2mat(get(visible_axes,'Parent'));
uparents = unique(parents);
for i=1:length(uparents)
copyobj(visible_axes(parents==uparents(i)),figure)
end
end
end
In a figure, graphical objects are organized hierarchically and can all be handled individually. For instance, axes is a child of a figure, plot is a child of an axes, and legends are build as axes.
The following example plots 2 lines (red and blue, with legends), then mixes plots and legends using copyobj.
figure;
subplot(1,2,1)
hp1 = plot(1:10,'r')
hl1 = legend('red')
subplot(1,2,2)
hp2 = plot(1:10,'b')
hl2 = legend('blue')
hf = figure;
hax = axes;
copyobj(hp1, hax); %copy plot to axes
copyobj(hl2, hf); %copy legend to figure
Not tested with a GUI though.
I think the simpler solution is to save the axes of the figure you're about to save as a fig file.
h = figure(1);
x = linspace(1,100);
y = 2*x;
ax = findall(h,'type','axes');
plot(x,y);
save('youraxes', 'ax');
hgsave(h, 'yourfig.fig');
I'm using Matlab R2012a, alternatively in R2013a or b the function to save the fig is now savefig.
Once you have obtained the axes handle you can find the corresponding legend handle using
legend_handle = legend(axes_handle)

realtime plotting in matlab using SURF

i want to plot a 3d graph using surf in matlab. i know how to plot it just using surf:
k = 5;
n = 2^k-1;
[x,y,z] = sphere(n);
c = hadamard(2^k);
p=surf(x,y,z);
but i want to plot this in realtime, and i want to update the values using set.
I tired:set(p,"XData",Xvalue,"YData",Yvalue,"ZData",Zvalue); but its giving me errors. has anyone plotted using surf in realtime?
1) you can use the linkdata command or toolbar button (or even Tools -> Link from the plot window)
2) programmatically: you need to call the command 'refreshdata' to signal that new data is available:
%% Define the data
t=linspace(0,2*pi,40);
y=sin(t);
%% Create the plot and set teh datasources
h=plot(t,y)
set(h,'YDataSource','y')
set(h,'XDataSource','t')
%% Now update the data and the plot
pause
y=sin(2*t);
refreshdata
This shows it for the plot, but expect surf will behave the same.