Matlab GUI. Set pushbutton handles in another .m file - matlab

I have a big Matlab code and now I am trying to connect it to GUI. I have created a function
function z = interface_master(handles)
which first gets initial parameters from GUI text edit box and then runs a number of .m files using these parameters, for example
n = get(handles.n_value,'String');
n = str2num(n);
assign('base','n',n)
run('code_1')
run('code_2')
...
Within this 'codes' I create and save a number of figures. I would like now for the User to be able to display a figure of his choice within GUI. Lets say I will have 3 different push buttons (Push1, Push2, Push3) and User after pressing Push1 will get Figure_A displayed. Then after pressing Push2, he will get Figure_B replacing Figure_A, and so on. Can I somehow make it work just setting handles in my function interface_master?
I don't want to overcrowd my interface.m file and so far I managed to do everything else (reading values, displaying messages) in this additional interface_master file, by just connecting both through interface_master(handles) in the interface callback functions. But now I am stuck with these push buttons.
I would really appreciate some help here. I have never done any GUI before.

I have created a very much simplified version of what I am doing. In general code_1 and code_2 are much much bigger and the interface will be displaying more messages, while code_1 and code_2 save around 20 different figures. But what I am struggling with can be demonstrated by a simple code calculating polynomials.
%% code_1.m
x = linspace(-1,1) ;
y = x.^n ;
%% code_2.m
f = figure('visible','off');
plot(x,y);
set(f,'Visible','on')
saveas(f,'power_plot_1','fig')
delete(f)
g = figure('visible','off');
plot(x,x.^(n+1));
set(f,'Visible','on')
saveas(g,'power_plot_2','fig')
delete(g)
%%% master.m
function z = master(handles)
n = get(handles.n_value,'String')
n = str2num(n) ;
assignin('base','n',n)
if (n < 1)
message = ('small n') ;
elseif (n>10)
message = ('large n') ;
else
message=('hello world') ;
run('code_1')
run('code_2')
end
set(handles.text1,'String',message)
and here is the interface:
https://lh3.googleusercontent.com/-5zoGVwgJhoM/V1qdiyd667I/AAAAAAAACQ0/oaTQHYn13gIuLoSb42Q7N66AV102e-VjQCCo/s912/inter.png

Related

Hide lines of code in MATLAB

I want to know If it's possible and how, to hide some parts of a line or whole lines of code from a script in MATLAB. For example:
if a=b
x=y+1; x=x^2;
end
And have the x=x^2 hidden, but still run the process. I mean:
if a=b
x=y+1;
end
(wringing hands with evil grin on face)
If you really want to mess with people like this, you're going to want to go down the operator overloading route. Come with me on a journey where you will almost certainly shoot yourself in the foot while trying to play a joke on someone else!
(lightning crackles over the laughter of a madman)
I've discussed this in a few other questions before (here and here). Basically, you can change the default behavior of built-in operators for MATLAB data types. In this case, we'll change how the plus operator works for variables of class double (the default variable type). Make a folder called #double on your MATLAB path, then create a file called plus.m and put the following code inside it:
function C = plus(A, B)
C = builtin('plus', A, B);
if strcmp(inputname(1), 'y')
C = C.^2;
end
end
Now, try it for yourself...
>> y=1; % Initialize y
>> x=y+1
x =
4 % Wait a minute...
>> x=1+1
x =
2 % OK
>> x=1+y
x =
2 % OK
>> x=y+1
x =
4 % What?!
>> x=y+2;
x =
9 % No!!
>> y=3;
>> x=y+1
x =
16 % Oh noes! I've been hax0red!!11!1!
How it works:
The new plus function shadows the built-in one, so it gets called when performing addition on doubles. It first invokes the built-in plus to do the actual addition using the builtin function. This is necessary, because if you wrote C=A+B; here it would call the phony plus again and cause infinite recursion. Then, it uses the inputname function to check what the variable name of the first input to the function is. If it's 'y', we square the result before returning it.
Have fun!!!
...and remember to remove it when you're done. ;)
if a==b
x = y+1;
for ind = 1
x = x^2;
end
end
Bit of a wacky way, but you can collapse loop/end blocks like for and while loops. Simply click the - sign in the editor:
So for two or less lines this doesn't help you, but if you want to hide e.g. 40 lines, it shortens it appreciably.
Another option is to simply chuck in a hundred or so spaces and make it obfuscated:
if a==b
x = y+1; x = x^2;
end
Thanks to excaza the most obfuscated way of all to write x=x^2;:
eval(cast((sscanf('240,122,240,188,100,118', '%d,')./2)', 'like', ''))

Looping a Function in Matlab

total newbie here. I'm having problems looping a function that I've created. I'm having some problems copying the code over but I'll give a general idea of it:
function[X]=Test(A,B,C,D)
other parts of the code
.
.
.
X = linsolve(K,L)
end
where K,L are other matrices I derived from the 4 variables A,B,C,D
The problem is whenever I execute the function Test(1,2,3,4), I can only get one answer out. I'm trying to loop this process for one variable, keep the other 3 variables constant.
For example, I want to get answers for A = 1:10, while B = 2, C = 3, D = 4
I've tried the following method and they did not work:
Function[X] = Test(A,B,C,D)
for A = 1:10
other parts of the code...
X=linsolve(K,L)
end
Whenever I keyed in the command Test(1,2,3,4), it only gave me the output of Test(10,2,3,4)
Then I read somewhere that you have to call the function from somewhere else, so I edited the Test function to be Function[X] = Test(B,C,D) and left A out where it can be assigned in another script eg:
global A
for A = 1:10
Test(A,2,3,4)
end
But this gives an error as well, as Test function requires A to be defined. As such I'm a little lost and can't seem to find any information on how can this be done. Would appreciate all the help I can get.
Cheers guys
I think this is what you're looking for:
A=1:10; B=2; C=3; D=4;
%Do pre-allocation for X according to the dimensions of your output
for iter = 1:length(A)
X(:,:,iter)= Test(A(iter),B,C,D);
end
X
where
function [X]=Test(A,B,C,D)
%other parts of the code
X = linsolve(K,L)
end
Try this:
function X = Test(A,B,C,D)
% allocate output (it is faster than changing the size in every loop)
X = {};
% loop for each position in A
for i = 1:numel(A);
%in the other parts you have to use A(i) instead of just A
... other parts of code
%overwrite the value in X at position i
X{i} = linsolve(K,L);
end
end
and run it with Test(1:10,2,3,4)
To answer what went wrong before:
When you loop with 'for A=1:10' you overwrite the A that was passed to the function (so the function will ignore the A that you passed it) and in each loop you overwrite the X calculated in the previous loop (that is why you can only see the answer for A=10).
The second try should work if you have created a file named Test.m with the function X = (A,B,C,D) as the first code in the file. Although the global assignment is unnecessary. In fact I would strongly recommend you not to use global variables as it gets very messy very fast.

How to update a uitable after creation from other functions?

I created a matfile in which I store data that are constantly overwritten by user behavior. This occurs in a function "test()".
n=1
while n < 5
myVal = double(Test704(1, 780, -1)) %Returns the user's behavior
if myVal == 1
n = n + 1 %"n" is the overwritten variable in the matfile
end
save('testSave1.mat') %The matfile
m = matfile('testSave1.mat')
end
Then, I want to display these data in another function (it is essential to have two separated functions) called "storageTest()". More particularly, storageTest() is a GUI function where I developped an uitable "t". So, I first call the function "test()" and give its output values as data of "t". Here is the code of the interesting part of "storageTest":
m = test()
d = [m.n]
t = uitable('Data',d, ...
'ColumnWidth',{50}, ...
'Position',[100 100 461 146]);
t.Position(3) = t.Extent(3);
t.Position(4) = t.Extent(4);
drawnow
This code executes only when "m = test()" running is over and displays me a tab in which I can see the final value of "n". However, I want my table to be displayed before and to see my value incrementing according to user's behavior.
I have searched on the web to solve my issue, but I cannot find any answer, is it possible to do such a thing?
Assuming I'm interpreting the question correctly, it should be fairly trivial to accomplish this if you initialize your table prior to calling test and then pass the handle to your table for test to update in the while loop:
For example:
function testGUI
% Initialize table
t = uitable('ColumnWidth',{50}, 'Position',[100 100 461 146]);
test(t)
function test(t)
n = 1;
while n < 5
n = n + 1;
t.Data = n;
pause(0.25); % Since we're just incrementing a number, a slight so we can actually see the change
end
When you run the above, you'll notice the data in your table iterating as expected.
excaza was a little faster in writing basically the same answer like me. As it looks a slightly different, I'll post it anyway.
function storagetest()
close all
f = figure;
data = [1];
t = uitable(f,'Data',data,'ColumnWidth',{50});
test()
end
function test()
% handle uitable
t = evalin('caller','t')
n = 1;
while n < 5
newVal = input('Enter a number:');
data = get(t,'Data');
set(t,'Data', [data; newVal]);
n = n + 1;
end
end
The "user behaviour" I imitated with the input function. The basic idea is to update your table from within test(). evalin you can use, if you don't want to pass parameters to test(), though passing the handle of the uitable directly is certainly the better option.
If you are working on a serious GUI project I highly recommend you reading this answer.

MATLAB GUI User Input Update

I have a MATLAB GUI which takes values from the user input , do some calculation based on those and plot them in the GUI.
Everything is all right and working BUT when I change the values in the GUI it does not plot as expected and gives and error of dimension mismatch. However, there is no dimension mismatch and if I go to the script and press run again (the big green arrow) and then click plot again, it plots the values as expected.
I have initialized all of my values that I use but I can not see how can fix this. I need something like update command for all of the script each time I press the 'plot' button.
Any help is appreciated, many thanks!..
CODE:
a = str2double(get(handles.edit14,'String'));
b = str2double(get(handles.edit15,'String'));
c = str2double(get(handles.edit16,'String'));
d = str2double(get(handles.edit18,'String'));
e = str2double(get(handles.edit19,'String'));
f = str2double(get(handles.edit20,'String'));
for Veff=[a:b:c] %user input speeds (a,b,c) (comes from user)
q = 0.5*1.225*(Veff*1000/3600)^2;
F1=q*S; M1=q*S*Cref;
FX1=(F1*coef(:,1)); FZ1=(F1*coef(:,3)); MM1=(M1*coef(:,5));
W=[d*g:e*g:f*g]; %define mass range (d,e,f comes from user)
for lw=1:1:length(W)
XGEquation2max1 = ((((-FB*(Xa-Xb))-(((FX1(12)))*(Za-Zr))-(((FZ1(7))))*(Xa-Xr))-((max(MM1))))./W(lw)) + Xa;
CGPercent(lw,column) = (XGEquation2max1 - Cstart)/Cref * 100;
end
column=column+1;
end
speed_matrix = [a:b:c];
mass_matrix = [d:e:f];
ns = size(speed_matrix);
ns= ns(2);
count5 = 1;
for ns=1:1:ns
hold all
axes(handles.axes4)
plot(CGPercent(:,ns),transpose(mass_matrix)/1000)
count5 = count5 + 1;
end
Main problem is with the variables 'd,e,f' because when I change 'a,b,c' only (i.e speed) there is no problem.

Update a M.file variables from command windows in Matlab?

I have a simple but interesting question. i tired hard to google it but my google got upset and giving me the same results...
i wanted to know is it possible to Update a constant variable form workspace command..
A Simple Example:
function y =StupidQuestion
a = 10; % some value
b =[5,6,7;1,2,8]; % some value
y = b*a % some operation
I forget to tell you that we can do it with simulink block by using below command
set_param('obj', 'parameter1', value1, 'parameter2', value2, ...)
i Want to use the assigned value for 3 weeks and without any reason i wants to change my values [a,b] to other but through command windows. any Idea. Waiting for your interesting Reply...................
You can set defaults for the inputs:
function y = foo(a,b)
if nargin < 1 || isempty(a), a = 10; end
if nargin < 2 || isempty(b), b = [5,6,7;1,2,8]; end
y = b*a
end
You can call foo() without inputs (and it will use the defaults for a and b) or supply your own values as: foo(12), foo(12,[10,20]), foo([],[23,23]), etc...
A possible way is to save some variables in an external file. Note that in this case a and b are only in the function workspace (you won't see their values unless you load the contents of test.mat separately). I'm passing the filename in rather than hard-coding it in case you need to switch between multiple settings.
Personally I would prefer to have a human-readable data file, but the concept remains the same (you'd just need some parser function which returned values for a and b given a file).
a = 10; % some value
b =[5,6,7;1,2,8]; % some value
save('test.mat','a','b');
clear a b;
function y = savedvariables(filename)
load(filename);
y = b*a; % some operation
end
y = savedvariables('test.mat');