I've got the following code for a Push-button in a GUI, where it asks for a pair of coordinates (X,Y), saved in a vector Z.
I want it to save different .mat files with different names (I've achieved that already) for a specific number of iterations (3 in this case), clearing the edit boxes each time a value of Z is saved. The problem is that it overwrites the past values, keeping only the last one in the first file, and generating NaN's on the other ones.
Any help will be greatly appreciated.
function pushbutton1_Callback(hObject, eventdata, handles)
folder=pwd; %Current folder
x=str2double(get(handles.edit1,'String'));
y=str2double(get(handles.edit2,'String'));
z=[x y];
k=1;
ng=3;
while k<=ng
baseFileName=sprintf('data%02d.mat',k);
fullFileName=fullfile(folder,baseFileName);
save(fullFileName);
S.(sprintf('z%d',k))=z;
save(baseFileName,'-struct','S');
k=k+1;
if k<=ng;
set(handles.edit1,'String','')
set(handles.edit2,'String','')
x=str2double(get(handles.edit1,'String'));
y=str2double(get(handles.edit2,'String'));
z=[x y];
end
end
Related
Is there any possible way to open the desired figures from a lot of plotted figures in MATLAB?
If it is possible with dialogue box then it will be perfect.
I have like 75 figures plotted after my code but I have closed the figures at end of loops as they are too much.
Is it possible to open just one figure by just entering values necessary for plotting figure in MATLAB at end of program?
One way to do this is the following:
1) You save the figures as .fig in a dedicated folder using the saveas command, e.g.:
saveas(gcf,['FileName_',num2str(idx),'.fig']);
where idx is the index associated with the figure number (so in 75 in the example you mentioned). For simplicity, I would save all of them in one folder.
2) You use inputdlg to create an input dialog box, where you type in the index you want. Then, you run uiopen(['FileName_',idxFromInput,'.fig']), which will display the figure. Note that the output from inputdlg is normally a string, so you don't need num2str here.
From Wikibooks: MATLAB Programming/Handle Graphics (emphasis mine):
Every time you close a figure, either by using the close function OR by hitting the 'X', you can no longer access the data, and
attempts to do so will result in an error. Closing a figure also
destroys all the handles to the axes and annotations that depended on
it.
This means that once you close your 75 figures, they are gone for good.
I would suggest saving all your figures to .fig file format, because this will allow you to open them later in MATLAB.
Take the following example:
x = linspace(0, 2*pi); % Sample data.
for i = 1:3 % Loop 3 times.
h = figure; % Create figure window and capture its handle.
plot(i*sin(x)); % Plot some data.
saveas(h, sprintf('fig%d.fig', i)); % Save figure to .fig file format.
close(h); % Delete the figure.
end
Now you can tell MATLAB to open one of the figures using the openfig function. For example, let's open the second figure fig2.fig. Go to the Command Window and type openfig('fig2') (including the .fig extension in the file name is optional).
>> openfig('fig2')
ans =
Figure (1) with properties:
Number: 1
Name: ''
Color: [0.9400 0.9400 0.9400]
Position: [520 371 560 420]
Units: 'pixels'
Show all properties
I want to create a frontend where the user can browse pictures forward by pressing Enter.
Pseudo-Code
hFig=figure
nFrames=5;
k=1;
while k < nFrames
u=signal(1*k,100*k,'data.wav'); % 100 length
subplot(2,2,1);
plot(u);
subplot(2,2,2);
plot(sin(u));
subplot(2,2,3);
plot(cos(u));
subplot(2,2,4);
plot(tan(u));
% not necessary but for heading of overal figure
fprintf('Press Enter for next slice\n');
str=sprintf('Slice %d', k);
mtit(hFig, str);
k=k+1;
keyboard
end
function u=signal(a,b,file)
[fs,smplrt]=audioread(file);
u=fs(a:b,1);
end
where
something is wrong in updating the data because pressing CMD+Enter increases k by one but does not update the data. Sometimes (rarely), the data is once the next iteration.
something is wrong with while's condition because k can be bigger than nFrames. keyboard just keep asking for more inputs.
My mistake earlier in Error-Checking
I had earlier a problem where the closure of the window lead to the crash of the application. I include this here because I mentioned a problem about it in the comment of one answer. I avoid the problem now by
hFig=figure;
n=5;
k=1;
while k<nFrames
% for the case, the user closes the window but starts new iteration
if(not(ishandle(hFig)))
hFig=figure;
end
...
end
which creates a new Figure if the earlier was closed by the user.
I tried unsuccessfully putting hFig=figure; inside the while loop's if clause earlier to avoid repetition in the code.
Please, let me know if you know why you cannot have the handle hFig in the while loop's if clause.
How can you loop subplots with updated outputs in Matlab?
To stop the script waiting for an input from the user you should use input instead of keyboard.
Actually keyboard makes your script entering in a debug mode. It stops the executino of the script as (like a breakpoint) allowing the user to, for example, check the value of a variable.
You can modify your scripr as follows (modification are at the end of your script, identified by "UPDATED SECTION):
hFig=figure
nFrames=5;
k=1;
while k < nFrames
u=signal(1*k,100*k,'handel.wav'); % 100 length
subplot(2,2,1);
plot(u);
subplot(2,2,2);
plot(sin(u));
subplot(2,2,3);
plot(cos(u));
subplot(2,2,4);
plot(tan(u));
% not necessary but for heading of overal figure
%
% UPDATED SECTION
%
% Use the string "Press Enter for next slice\n" as the prompt for the
% call to "input"
%
% fprintf('Press Enter for next slice\n');
% str=sprintf('Slice %f', k);
% Use %d instead of "%f" to print integer data
str=sprintf('Slice %d', k);
mtit(hFig, str);
k=k+1;
% Use "input" instead of "keyboard"
% keyboard
input('Press Enter for next slice\n')
end
Hope this helps.
Qapla'
I'm processing vast amount of data (>>100k lines) with variable step.
I would like to create figure and plot the processed data as they are counted (for termination of the running script when something goes wrong, or for impressing the "customers" with the fancy progress "animation").
Suppose we have `sourcefile.txt' with one column of positive numbers X(n) on row n and:
There is plenty of lines with X(n+1) < X(n),
X(n+N) > X(n); where N goes from thousands for small n to tens for large n.
I've thought of:
fID=fopen('sourcefile.txt');
figure;axes; % create figure
act='0';threshold=0;N=0;DATA=0;ii=0;
while ischar(act) % loop until end of file.
ii=ii+1;N=0;
while temp<threshold&&ischar(act) % loop until threshold is overflown (next step) or end-of-file is reached.
act=fgetl(fID);
temp=temp+str2double(act);
N=N+1;
end
line('xdata',ii,'ydata',temp/N,'Marker','o') % New point should appear
threshold=threshold+0.5; % Continue with new stopping rule.
end
The problem is that the loops are entered and processed and then figure is created. How can I force MATLAB to create a figure and then to calculate/update plotted data?
Try inserting drawnow after you draw the line using line. This will flush the graphics buffer and update your figure immediately. If you don't do this, your figure will appear blank until the loop finishes, and then the figure will appear with your objects that you added to the figure.
So to be specific with what I talked about:
fID=fopen('sourcefile.txt');
figure;axes; % create figure
act='0';threshold=0;N=0;DATA=0;ii=0;
while ischar(act) % loop until end of file.
ii=ii+1;N=0;
while temp<threshold&&ischar(act) % loop until threshold is overflown (next step) or end-of-file is reached.
act=fgetl(fID);
temp=temp+str2double(act);
N=N+1;
end
line('xdata',ii,'ydata',temp/N,'Marker','o') % New point should appear
%%%%%%%%%%%%// Change here
drawnow;
threshold=threshold+0.5; % Continue with new stopping rule.
end
Therefore, once you draw a line, the figure should immediately update itself and so for each iteration, the figure should update with a new line object.
I have two GUIs. In the first gui I want to plot an input signal (ex: sine signal). My problem is, how can I plot back the same signal in the second GUI after I clicked the 'load' pushbutton in the second GUI? Can somebody help me? I really need help.
Here is some code to get you going about using setappdata and getappdata. This is very basic and there are things which I did not mention (eg using the handles structure or passing variables as input arguments to functions) but using setappdata and getappdata is a safe way to go.
I created 2 programmatic GUIs. The code looks a bit different than when GUIs are designed with GUIDE, but the principle is exactly the same. Take the time to examine it and understand what everything does; that's not too complicated.
Each GUI is composed of one pushbutton and an axes. In the 1st GUI (sine_signal) the sine wave is created and displayed. Pressing the pushbutton opens the 2nd GUI (gui_filtering) and calls setappdata. Once you press the pushbutton of that 2nd GUI, setappdata is called to fetch the data and plot it.
Here is the code for both GUIs. You can save them as .m files and press "run" in the sine_signal function.
1) sine_signal
function sine_signal
clear
clc
%// Create figure and uicontrols. Those will be created with GUIDE in your
%// case.
hFig_sine = figure('Position',[500 500 400 400],'Name','sine_signal');
axes('Position',[.1 .1 .8 .8]);
uicontrol('Style','push','Position',[10 370 120 20],'String','Open gui_filtering','Callback',#(s,e) Opengui_filt);
%// Create values and plot them.
xvalues = 1:100;
yvalues = sin(xvalues).*cos(xvalues);
plot(xvalues,yvalues);
%// Put the x and y values together in a single array.
AllValues = [xvalues;yvalues];
%// Use setappdata to associate "AllValues" with the root directory (0).
%// This way the variable is available from anywhere. You could also
%// associate the data with the GUI itself, using "hFig_sine" instead of "0".
setappdata(0,'AllValues',AllValues);
%// Callback of the pushbutton. In this case it is simply used to open the
%// 2nd GUI.
function Opengui_filt
gui_filtering
end
end
And
2) gui_filtering
function gui_filtering
%// Same as 1st GUI.
figure('Position',[1000 1000 400 400],'Name','sine_signal')
axes('Position',[.1 .1 .8 .8])
%// Pushbutton to load data
uicontrol('Style','push','Position',[10 370 100 20],'String','Load/plot data','Callback',#(s,e) LoadData);
%// Callback of the pushbutton
function LoadData
%// Use "getappdata" to retrieve the variable "AllValues".
AllValues = getappdata(0,'AllValues');
%// Plot the data
plot(AllValues(1,:),AllValues(2,:))
end
end
To show you the expected output, here are 3 screenshots obtained when:
1) You run the 1st GUI (sine signal):
2) After pressing the pushbutton to open the 2nd GUI:
3) After pressing the pushbutton of the 2nd GUI to load/display the data:
That's about it. Hope that helps!
I'm trying to write a small function which should read a matrix of doubles, make a plot for all columns separately (and display the last row as line, as this is the mean) and save the plot.
All commands work when I tried them on the command line, but when I run them as a script it doesn't work. The plots are not entered in the figure (only ticks and labels are redrawn). When I copy the single commands in debug mode to the command line it works.
So what am I doing wrong here?
I'm loading a matrix 'corr' prior to this loop..
for i=1:30; % number of components
corr_fig(i)=figure;
hold;
plot(corr(1:length(sub),i));
line ([0 (length(sub))],[(corr(length(sub)+1)) (corr(length(sub)+1))], 'Color','m')
set(gca,'XTick',[1:(length(sub))])
set(gca,'XTickLabel',{sub{1:length(sub)}})
title(['Correlations for',num2str(i)])
saveas(corr_fig(i),['corrs_for_',num2str(i)],'fig');
hold off;
close all;
end
Throw in a 'drawnow' command in the loop. This flushes out the plotting buffer and forces MATLAB to create the figure, rather than trying to skip that step due to what the compiler sees happening in the loop.
For example, this:
for k = 1:100;
figure()
plot(rand(100, 1), rand(100, 1))
close all
end
draws nothing (never shows a figure window), but this:
for k = 1:100;
figure()
plot(rand(100, 1), rand(100, 1))
drawnow
close all
end
does what you would expect.
Thanks for all the answers! Figured it out on my own in the end. The code is fine, well mostly. I haven't assigned a proper variable name to the matrix I handed to the function and was not calling this name in the loop corectly (MAT.corr would have been it..) Now it's working.. Stupid me! Thanks nevertheless!