MATLAB - updating plot in gui? - matlab

Getting started with matlab guide, hit a stumbling block. Got it as simple as I can as a toy gui to illustrate my problem. A gui (named asas) has a pushbutton and an axis. The callback of the button reads
axesHandle= findobj(gcf,'Tag','axes1');
x=rand(randi(10+20,1),4);
plot(axesHandle, x)
There's no other code written by me (guide wrote it).
The 1st time I push the button, everything is fine: the plot gets done. The 2nd time around, I get an error, from the console:
Error using plot
Vectors must be the same lengths.
Error in asas>pushbutton1_Callback (line 83)
plot(axesHandle, x)
Error in gui_mainfcn (line 96)
feval(varargin{:});
etc...
I want to plot the new data x, replacing the old one.
It looks like matlab is not replacing the data to plot, but somehow trying to append to the plot?
I have searched, but haven't found anything that applies.

The explanation is not straightforward - and certainly not if you are new with MATLAB and its handle graphics subsystem.
Your code as it is, line by line:
axesHandle= findobj(gcf,'Tag','axes1');
x=rand(randi(10+20,1),4);
plot(axesHandle, x);
The first line attempts to locate in the current figure (gcf, "get current figure") any child object with the property 'Tag' set to the string 'axes1'. I guess you are aware of this? The second line of course generates some random data to plot. The third line plots the data in x.
But after the plot-call the property 'Tag' is actually reset to '' (the empty string), which in turn makes findobj fail in any subsequent searches for the axes-handle. The variable axesHandle with therefore NOT contain an actual handle but instead the empty matrix []. This will make plot default to another mode an interpret the empty matrix as data for the x-axes (the first argument to plot). This expectedly results in the error you receive:
...
Error using plot Vectors must be the same lengths.
...
The solution by Dan in the comment above is a workaround, but there is good sense in telling plot where to plot - especially in GUIs.
You can instead add a fourth line:
set(axesHandle,'Tag','axes1');
This will set property 'Tag' back to 'axes1' and any subsequent clicks on the button should now also work. And you can add more than one axes-objects now. If that is what you want to.

Related

Running MATLAB function without defining all parameters

I have a Matlab function
PlotSubbands(imfx(:,1),wx,3,3,j,j,1);ylabel('Subband');
from TQWT toolbox. eeweb.poly.edu/iselesni/TQWT. When I execute, the function plots 'j' number of plots. (I have not included full code). The function plots the input signal, which is in this case imfx(:,1) for every subplot. And this what I don't want. I tried removing it from the parameters but I got error, 'not enough input arguments'. This is because in the function the first input signal parameters is defined and used. I cannot remove it from there. Appreciate your inputs on the same. Thank you.
The function PlotSubbands include following lines
if isreal(x)
plot((0:N-1)/fs,x/(2*max(abs(x))),'b')
else
plot((0:N-1)/fs, real(x)/(2*max(abs(x))), 'black')
The repeated plotting of input signal is done from these two line. Commenting these lines can solve the problem (If array x does not include imaginary part, then better to comment these lines). However, the to determine the real array, isreal(x) is needed further in the function. So, I defined the value of x here and it solved the repeated plotting issue.

Passing DurationTickFormat argument fails when done via a struct

In Matlab I wanted to pass arguments to the plot function by using a struct. This was going well until I wanted to include the DurationTickFormat argument.
In the minimal example below, I get the following error message when trying to plot the second figure:
Error using duration/plot There is no DurationTickFormat property on
the Line class.
clear;
t_dur = days(0);
t_dur(2) = 2;
t_duration = linspace(t_dur(1),t_dur(2),11);
figure;
plot(t_duration,0:10,'Color','k','LineWidth',2,'DurationTickFormat','hh:mm:ss');
% using a struct to pass arguments to the plot function
plotOptions.LineWidth = 2;
plotOptions.DurationTickFormat = 'hh:mm:ss';
figure;
plot(t_duration,0:10,'Color','k',plotOptions);
Any ideas why using a struct to pass arguments doesn't work in this case?
Thanks.
I'm not familiar with R2015a, but I have a good guess. I think when you pass a structure, you explicitly add line properties (lineseries properties in older matlab, I guess with HG1, chartline properties in the newest ones, I'm guessing with HG2). The chartline properties do not include 'DurationTickFormat'. So when you are calling it directly, you are actually telling the plot function to do some stuff (like changing the xlabel accordingly, which is obviously invisible to a line object).
I hope someone familiar with R2015a can either verify or disprove my hypothesis.
Update: from plot options > DurationTickFormat:
DurationTickFormat is not a chart line property. You must set the tick format using the name-value pair argument when creating a plot.

matlab zoom callback error associated with text function

While trying to execute generation of a series of text boxes in a post-zoom callback function in Matlab, a number of errors are generated, the trace of which is unhelpful in diagnosing and resolving the problem. When the text generation is in the main body of code as follows, the code executes properly and there is no issue executing the minimal post-zoom callback function:
string='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
offset=8;
h=figure;
z=zoom(h);
set(z,'ActionPostCallback',#post_callback);
[ax,plt1,plt2]=plotyy(14:20,1:7,15:17,1:3,#bar,#bar)
ylim([0 10]);
hold on;
set(plt2,'FaceColor','r');
xLim=xlim(gca);
for i=xLim(1)+1:xLim(2)-1
text(i,8,string(i-offset+1),'Clipping','on');
end
function post_callback(obj,evd)
xLim = get(evd.Axes,'XLim');
However, if the text box generation is moved to the #post_callback function, a series of errors result:
string='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
offset=8;
h=figure;
z=zoom(h);
set(z,'ActionPostCallback',#post_callback);
[ax,plt1,plt2]=plotyy(14:20,1:7,15:17,1:3,#bar,#bar)
ylim([0 10]);
hold on;
set(plt2,'FaceColor','r');
function post_callback(obj,evd)
xLim = get(evd.Axes,'XLim');
for i=xLim(1)+1:xLim(2)-1
text(i,8,string(i-offset+1),'Clipping','on');
end
Those errors are, as described in this problem:
Warning: An error occurred during the mode callback.
> In uitools.uimode.fireActionPostCallback at 14
In zoom>local2DButtonUpFcn at 1332
In hgfeval at 63
In uitools.uimode.modeWindowButtonUpFcn at 46
In uitools.uimode.setCallbackFcn>localModeWindowButtonUpFcn at 58
Could someone please enlighten me as to the root cause of the errors?
The error seems to be the same. You should try to use the debugger here. Set a breakpoint in your post callback function. However, there are a few problems in your code. Some are implementation issues, some other problems does not do what you ask them too. You seems to have some programming experience, so I guess that most implementation issue are just bugs. I will list problems and solutions.
1) I cry when I see that you use string as a variable. String is an abstract type (obselete in matlab now since later versions uses char vectors). use instead some other name like str or myString.
2) Unless offset and your variable string is not declared global, they will not be inside the scope of post_callback. Different from C or C++, a variable does not become global when defined in "main" (since you do not even define a main method). If you want to use string or offset inside of post_callback, you must define them inside their scope (inside the function).
3) the loop variable i must not be a cell. Use the method from the previous question to convert it to a double vector.
4) The loop variable i must be an integer in:
text(i,8,string(i-offset+1),'Clipping','on');
since string is defined a variable and variable indices must be integers, xLim does not necessary need to be an integer.
5) I do not think text will give the expected output here. What text does is creating a string and linking it to a point on the plot. This means that every time you zoom you will have a new text in the plot. Unless the texts are located at exactly the same place (which may be possible, but will reqire a lot of work) the plot will look really ugly. If possible, place the text strings in the way that you do in example 1 and remove it from post_callback.

How do I tell my MATLAB GUI that I want to plot on it using an external .m file?

I have a GUI(made using GUIDE) in which there is an axes on which I can draw. When I saved the gui, i have a .fig file and a .m file (whose names are start_gui.m and start_gui.fig). Now, I am trying to plot on these axes using an external M file, to which I have passed the GUI handles. This is as follows:
function cube_rotate(angle1,angle2,handles)
gcf=start_gui.fig; %this is the name of the gui.fig file in GUIDE
set(gcf,'CurrentAxes',handles.cube_axes)%this allows us to plot on the GUI
%plot something
end
handles.cube_axes is the name of the handle in the GUI created using guide. Inspite of passing the handles, it won't allow me to plot in the gui. It throws up an error saying:
??? Undefined variable "start_gui" or class "start_gui.fig".
start_gui.fig is the name of the GUI figure that was generated in GUIDE. How do i make it plot in the axes in start_gui.fig?
Thanks for all the help!
You've made a few errors. The first is referring to a file name without single quotes to denote a string. The second is trying to open an existing figure by assigning it as a variable named gcf. This will just give you a variable gcf which contains the string 'start_gui.fig'.
Instead, open the figure with this command:
fH = hgload('start_gui.fig');
% Then find/assign the axes handle (assuming you only have one axes in the figure):
aH = findobj(fH,'Type','axes');
% And finally plot to the axes:
plot(aH,0:.1:2*pi,sin(0:.1:2*pi));
On a secondary note, is there a reason you're not using the M-file generated by MATLAB to carry out this functionality? By using the auto-generated M-file, you'll be able to access the handles structure rather than using findobj.
The error you're getting is because of your second line: gcf=start_gui.fig;
It's looking for a variable named start_gui, which you don't have. (start_gui.fig is a filename, not a variable.)
To solve your plotting problem, take a look at this Mathworks support article.

MatLab Plotting Function Matrix Dimension Error

I have a simple function written
function[] = myfun(p,q)
fminbnd(#(x)myfun1(q,p,b),0,1)
where myfun1's output is from the function quad.
How do I plot myfun? I've tried fplot(#(x)myfun(1,x),0,1) but this gives me a matrix dimensions must agree error...
Your question does not contain enough information to identify exactly where the problem lies, but one issue is certainly that myfun does not return any output. What should fplot plot, if there is nothing returned by the function?
Try
function out = myfun(p,q)
%# you may want to define b here
out = fminbnd(#(x)myfun1(q,p,b),0,1);
If that doesn't fix the issue, turn on the debugging mode by typing dbstop if error at the command line. This will show where exactly the error occurs, and allow you to inspect the variables for correct shape.