matlab GUIDE: storing data from loop in vector - matlab

I am new to matlab and i need some help. I am trying to make some program, where you can by 2 clicks on picture get a lenght of something. Basicly it works well, but got a problem when trying to algorytmize it. I use ginput to get coordinates and then pythagorean theorem to work with them and make important variable z2. And those variables I want to store in vector so basicly: I pressed push_button1 click twice on a picture and get some z2,now when i do the procedure again i want to store the new one with the old one in the same vector
[z2_old z2_new]. But basicly every time i tried to make something like this the old ones value is rewritten.
This is the code of my push button:
function pushbutton1_Callback(hObject, EventData, handles)
%counter - number of press (working right)
counter = get(hObject, 'UserData') + 1;
set(hObject, 'UserData', counter);
set(handles.text1, 'String', sprintf('%d', counter));
% - ginput part (working right)
c2 = ginput(2);
q3 = text(c2(1,1),c2(1,2),'X', ...
'HorizontalAlignment','center', ...
'Color', [1 1 0], ...
'FontSize',10);
q4 = text(c2(2,1),c2(2,2),'X', ...
'HorizontalAlignment','center', ...
'Color', [1 1 0], ...
'FontSize',10);
%creating the z2 variable(working right)
x2=c2(1,1)-c2(2,1);
y2=c2(1,2)-c2(2,2);
z2=sqrt(x2*x2+y2*y2);
% - loop for getting a vector (not ok)
for i=1:counter
z(i,1)=z2
end
So, basicly when I run the button first time and z2 got for example 130, second time 60, third time 210m I want to get z=[130 60 210], now I am still getting something like 1st press:z=[130], 2nd press: z=[60 60], 3rd press: z=[210 210 210], the old values are every time lost. I tried to fix it many ways but its still not working. Its only a small part of my work and i almost run out of time.
Can someone please tell me how should that loop look like? I tried z(end+1)=z2 , z=[z z2] , but the result is always the same.
Thanks for your help a lot. I really Appreciate it.

The issue is that with each click on pushbutton, it creates new values for z2. Even though the counter increments, but z2 is always the new value. So, you need to save z2 between clicks on the pushbutton. For that you have handles structure available for data storage between GUI callbacks. You need to make two changes -
Add this line inside the guiname__OpeningFcn before the handles structure is updated in guidata(hObject, handles); -
handles.z2 =[];
Edit the pushbutton callback to this -
x2=c2(1,1)-c2(2,1)
y2=c2(1,2)-c2(2,2)
z2=sqrt(x2*x2+y2*y2)
z = [handles.z2 z2]
handles.z2 = z;
guidata(hObject,handles);
Hope this works out for you, let us know!

Try this
Remove the for loop
Just write
z[z,z2]
This should add z2 to the end of the existing z every time.
In case it throws an error just first give z(0)=0; an initial garbage value to start with.

Related

How to plot a "moving" graph for real time values along the x-axis (using psychtoolbox)?

I am writing a code for a real time experiment using psychtoolbox to present the stimulus. In my experiment, I need to show the subject a graph that indicates his performance. I have plotted the graph using this simple code:
% Draw the graph
figure('visible','off','color',[0 0 0]);
pcolor([0 Num_timepoint+2],[-10 0],ones(2,2));
hold on;
pcolor([0 Num_timepoint+2],[0 10],2*ones(2,2));
colormap([79 167 255;255 187 221]/256);
plot(1:subloop,value0,'*-',...
'color',[0,0,0],...
'LineWidth',1,...
'MarkerSize',5,...
'MarkerEdgeColor','k',...
'MarkerFaceColor',[0.5,0.5,0.5]);
axis([0,Num_timepoint+2,-10,10]);
saveas(gcf,'line_chart.png'); %save it
close(figure);
line_chart=imread('line_chart.png'); %read it
resized_plot=imresize(line_chart,0.5);
imageSize = size(resized_plot);
[imageHeight,imageWidth,colorChannels]=size(resized_plot);
bottomRect = [xCenter-imageWidth/1.5, yCenter+gapdown, xCenter+imageWidth/1.5, yCenter+gapdown+imageHeight];
imageDisplay=Screen('MakeTexture', win0, resized_plot);
Screen('DrawTexture', win0, imageDisplay, [], bottomRect);
Unfortunately, this simple code is very slow. In addition, I couldn't make the graph moving along x axis, as soon as the new value comes.
Any help would be Awesome. Thanks in advance for your efforts.
Why are you saving the figure and redisplaying as an image? Maybe I'm missing something but you should be able to accomplish what you need by updating the existing plot with the fresh data using the handles properties of the plot:
.... First time through we need the initial plot ....
% Set up figure with colormaps and such but leave as 'visible','on'
hPlot = plot(plot(1:subloop,value0,'*-',...
'color',[0,0,0],...
'LineWidth',1,...
'MarkerSize',5,...
'MarkerEdgeColor','k',...
'MarkerFaceColor',[0.5,0.5,0.5]);
hAxes = gca;
.... Loop over your real time updates ....
% Assuming value0 has subject's results from t=0 to t=now
hPlot.XData = value0; hPlot.YData = [1:subloop];
hAxes.XLim = [0 numTimePoints+2];
hAxes.YLim = [-10 10]
.... Continue test and update value0 ....
I think that should keep your plots current without having to save the figure as image to file then reopen the image to display to subject.
If you want to move your data one sample, you can use the circshift function. For example, if you want your new values to appear on the left hand side, you can shift all values 1 sample rightward, then add your new value in the first position.
For converting a MATLAB figure to a Psychtoolbox texture, you don't need to save, then load the temporary images. You can instead use the getframe function to capture the MATLAB figure data, which can then be given to MakeTexture to turn it into a Psychtoolbox texture.
I'm not sure what values you're actually using for subloop, value0, etc. but there is an example that I think might be close to what you want. In this example, 30 frames of figures are plotted, with each figure being on screen for 1 second. New data points are generated randomly and appear from the left hand side of the figure.
Depending on the details of your experiment, you may find that this approach is still too slow. You could also create the figure directly via Psychtoolbox drawing methods like DrawLines, etc. though that would require more effort.
try
win0 = Screen('OpenWindow', 0, 0);
Num_timepoint = 100;
subloop = 100;
value0 = zeros(1,100);
num_demo_frames = 30;
% Draw the graph
fig_h = figure('visible','off','color',[0 0 0]);
pcolor([0 Num_timepoint+2],[-10 0],ones(2,2));
hold on;
pcolor([0 Num_timepoint+2],[0 10],2*ones(2,2));
colormap([79 167 255;255 187 221]/256);
plot_h = plot(1:subloop,value0,'*-',...
'color',[0,0,0],...
'LineWidth',1,...
'MarkerSize',5,...
'MarkerEdgeColor','k',...
'MarkerFaceColor',[0.5,0.5,0.5]);
axis([0,Num_timepoint+2,-10,10]);
for f = 1:num_demo_frames
new_value = randn(1,1);
data_values = plot_h.YData;
data_values = circshift(data_values, 1);
data_values(1) = new_value;
plot_h.YData = data_values;
plot_values = getframe(fig_h);
imageDisplay=Screen('MakeTexture', win0, plot_values.cdata);
Screen('DrawTexture', win0, imageDisplay);
Screen('Flip', win0);
WaitSecs(1);
end
sca;
catch e
sca;
rethrow(e);
end

Matlab gui with pause function

I am using the GUIDE for matlab gui.
The gui built in order to communicate with keithley current measurement device through GPIB.
When using a toggle button for Current measurement while loop, i am using a pause() function inside the while loop for each iteration and a ytranspose on the y array reading results.
function Measure_Callback(hObject, eventdata, handles)
global GPIB1
global filename
global timeStep
disp('Measurement in progress \n stopwatch starts!');
tic
x=0;
n=0;
while get(hObject,'Value')
fprintf(GPIB1, 'printnumber(smua.measure.i(smua.nvbuffer1))');
fprintf(GPIB1, 'printbuffer(1,1,nvbuffer1)');
A = fscanf(GPIB1);
if length(A)<20
x = x+1;
n = n+1;
t(n) = toc ;
y(x) = str2double(A);
plot(t,y,'-bo',...
'LineWidth',2,...
'MarkerEdgeColor','k',...
'MarkerFaceColor',[.49 1 .63],...
'MarkerSize',10);
grid on
hold on
end
title('Current vs Time','FontSize', 15)
xlabel('Time [s]','FontSize', 15)
ylabel('Current [A]','FontSize', 15)
a = timeStep;
pause(a)
end
disp('Measurement terminated');
disp('Elapsed time: ');
elapsedtime = toc;
elapsedtime_string = num2str(elapsedtime);
disp(elapsedtime_string);
ytrans = transpose(y);
csvwrite(filename,ytrans);
fprintf(GPIB1, 'smua.source.output = smua.OUTPUT_OFF');
For the pause function i'm geting error:
?? Error using ==> pause Error while evaluating uicontrol Callback
For the transpose(y) function i'm also getting a error:
its undefined y.
Cant understand why are those errors and could use some help.
Thank you!
First off, as people say, post the errors and the code. Do you know if length(A) is smaller than 20 in the first time you run the loop? Because if not, A is not defined and you can't transpose something that is not there. Initialize A before the loop to something and see if the error persists (or print out length(A) to make sure the loop gets entered the first run).
As for the pause error, make sure pause is an int or double, not a string. If you get your global timeStep from the GUI field, it is probably a string and you need to covert it to double first.

Matlab uicontrol function modification

I'm working on a project in which some parts are concerned with TicTacToe game. I have the tictactoe.m file and would like to change the code so that the player's selection would be applied by a function's output, say,RESULT parameter rather than clicking on the screen by the user himself. the uicontrol part of my code is as follows. How may I control the game by another function's output instead of pushbutton style?
function B = buttons
% Initialize push buttons and text.
clf
shg
B = zeros(3,3);
M = magic(3); % strategical approach and equivalent game for TicTacToe game.
for k = 1:9
[i,j] = find(k == M);
B(i,j) = uicontrol('style','pushbutton','units','normal', ...
'fontsize',16,'callback','tictactoe(''green'')');
end
uicontrol('style','text','units','normal','pos',[0.30 0.82 0.40 0.10], ...
'fontsize',20,'background',get(gcf,'color'),'tag','toptext');
uicontrol('style','text','units','normal','pos',[0.20 0.72 0.60 0.10], ...
'fontsize',10,'background',get(gcf,'color'),'tag','toptext','string', ...
['Pick single digit numbers. Each digit can be chosen only once. ' ...
'Generate a total of 15 using exactly three digits.'])
uicontrol('style','pushbutton','units','normal','string','Game', ...
'fontsize',12,'position',[.23 .12 .15 .07], ...
'callback','tictactoe(''game'')');
uicontrol('style','pushbutton','units','normal','string','Start', ...
'fontsize',12,'position',[.43 .12 .15 .07], ...
'callback','tictactoe(''start'')');
uicontrol('style','pushbutton','units','normal','string','Exit', ...
'fontsize',12,'position',[.63 .12 .15 .07], ...
'callback','tictactoe(''exit'')');
All the push button is doing is executing a callback command. In this case the pushbutton 'Start' is calling
tictactoe('start')
So you can get another function to start the came by calling the same function, you will have to look at the function 'tictactoe' because it will need another couple of inputs, the pushbutton uicontrol automatically adds in the extra inputs, objects handles etc.

How in Matlab do changes on figure 1 with slider on figure 2?

I have some sliders on figure 1, and I have some images on figure 2. I want to do the callbacks for the sliders in a way that, when I change the sliders in figure 1 , the threshold changes and images update automatically in figure 2.
I'm using addlistener to send values for callback function. The problem is when you move slider the active figure is figure 1, and you want to do changes on figure 2.
adding some code for clarification:
M.rgbImage = imread('euhedral-mag-on-po-edge-pseudo-sub-ophitic-rl-fov-4-8mm.jpg');
[rows, columns, numberOfColorBands] = size(M.rgbImage);
F.f = figure; % This is the figure which has the axes to be controlled.
% Now create the other GUI
S.fh = figure('units','pixels',...
'position',[400 400 500 100],...
'menubar','none',...
'name','Image control',...
'numbertitle','off',...
'resize','off');
S.sl = uicontrol('style','slide',...
'unit','pix',...
'position',[60 10 270 20],...
'min',0,'max',255,'val',100,...
'callback',{#sl_call2,S},'deletefcn',{#delete,F.f});
....
lis = addlistener(S.sl,'Value','PostSet',#(e,h) sl_call3(S,F,M));
function sl_call3(S,F,M)
v = get(S.sl,'value');
figure(F.f), subplot(4, 4, 13);
M.redMask = (M.redPlane > v);
imshow(M.redObjectsMask, []);
set(S.ed(2),'string',v);
Create reference to both your figures:
f1=figure(1);
f2=figure(2);
And then when doing the callback pass f2 as a parameter.
In the callback, you'll have get the handle to the second figure.
There's various ways to do that.
You can specify the handle to the second figure at the time of callback-definition:
figure2 = ...;
addlistener(hSlider, ..., #(a,b) changeStuffOn(figure2));
Or during the callback:
function callbackFunction(hObject, evt)
% get the handle to the second figure, e.g. by a tag, or its name
fig2 = findobj(0, 'type', 'figure', 'tag', 'figure2'); %
% do whatever you want with fig2
end
The latter might be somewhat worse in performance, but e.g. has the benefit of working reliably even if figure2 was deleted and recreated and some point.
To avoid the change of focus you'll have to get rid of this line your callback:
figure(F.f)
This explicitly moves the focus to the second figure.
You'll have to use e.g. the imshow(axes_handle, ...) syntax, in order to show the image not in the "current axes".

Saving GUI data from matlab in a 3D matrix

I'd like to save matrices which are input via GUI pushbuttons in a 3D matrix. for example: I click button 1 a 2-2 matrix is put in the first slice of the 3D matrix. I than click button 3 and a different 2-2 matrix is put in the second slice. SO on and so on. I hope this is clear enough. The problem I have is that I'm not an experienced programmer. I currently initialize a zeros matrix as follows in the opening func:
storageMatrix = ones(2,2,100);
setappdata(0, 'storageMatrix', storageMatrix);
I have put a function updateStorageMatrix in the main script like this, mind you this isn't finished yet.
function updateStorageMatrix
storageMatrix = getappdata(0, 'storageMatrix');
and than when I look at my code of pushbutton 1 for example it looks like this:
% --- Executes on button press in Add_Straightduct.
function Add_Straightduct_Callback(hObject, eventdata, handles)
%prompt command for k number and length
prompt = {'k0:','Length:'};
dlg_title = 'Straight Duct specs';
num_lines = 1;
SDelements = {'0','0'};
Straightduct = inputdlg(prompt,dlg_title,num_lines,SDelements)
%insert values in function
sizeStorageMatrix = size(getappdata(0,'storageMatrix')); %get size of the storage matrix
dimT = sizeStorageMatrix(1,3); %take the number of matrices
if dimT==1
straightDuct = straight_duct(str2num(SDelements{1}), str2num(SDelements{2}), Mach_Frange(1,1))
setappdata(handles.updateStorageMatrix,'storageMatrix', storageMatrix(1:2, 1:2, 1))=straight_duct(str2num(SDelements{1}), str2num(answer{2}), Mach_Frange(1,1))
dimT+1
else
setappdata(0,'storageMatrix', storageMatrix(1:2, 1:2, dimT+1))=straight_duct(str2num(SDelements{1}), str2num(answer{2}), Mach_Frange(1,1))
dimT+1
end
the straight_duct() is a function I used in the script when calculating the mufflers, I have several of those functions, I am not sure if that's the way to work when using GUI. I just hope you get the idea of what I'm trying to achieve and help me on my way. So I can actually make a UI for my script :)
This assumes you've initialized the storageMatrix elsewhere in the GUI like this...
handles.storageMatrix = zeros(2,2,100);
guidata(hObject,handles); % Must call this to save handles so other callbacks can access the new element "storageMatrix"
Then in your first button's callback...
% --- Executes on button press in Add_Straightduct.
function Add_Straightduct_Callback(hObject, eventdata, handles)
.
. % Whatever initializations you need to do
.
localStorageMatrix = handles.storageMatrix; %load the storageMatrix being used by other callbacks/functions
.
. % Whatever you need to do to generate the new 2x2 matrix "slice"
.
localStorageMatrix(:,:,end+1) = newSlice; % appends the new slice to the end of the, indexing using colons assumes newSlice is of the same first and second dimension as other slices in localStorageMatrix
handles.storageMatrix = localStorageMatrix; % overwrite the storageMatrix in handles with the contents of the new localStorageMatrix
guidata(hObject,handles); % save the handles struct again now that you've changed it
Alternatively, you could have just used the handles.storageMatrix throughout, without including a localStorageMatrix but I've included it for emphasis.