Scilab - calling another GUI within a GUI. Functions not working - function

I'm quite new to scilab, I have created two GUIs (see example below), with script 2 being called from script 1. However the function in script 2 don't seem to work. Can anyone help?
Script 1
'//////////
f=figure('figure_position',[0,0],'figure_size',[1250,650]);
//////////
delmenu(f.figure_id,gettext('File'))
delmenu(f.figure_id,gettext('?'))
delmenu(f.figure_id,gettext('Tools'))
toolbar(f.figure_id,'off')
handles.dummy = 0 ;
handles.exam=uicontrol(f,'unit','normalized','BackgroundColor', [0.5,1,1],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[14],'FontUnits','points','FontWeight','bold','ForegroundColor',[0,0.5,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.5,0.5,0.1,0.05],'Relief','flat','SliderStep',[0.01,0.1],'String','exam','Style','pushbutton','Value',[0],'VerticalAlignment','middle','Visible','on','Tag','obj102','Callback','exam_callback(handles)')
function exam_callback(handles)
close(f);
clear
exec('costs0-1.sce',-1) ;
endfunction`
Script 2
////////// Defining the figure (size, name etc)/////////////////////////////
f=figure('figure_position',[0,0],'figure_size',[1250,650],'auto_resize','on','background',[8]);
//////////
delmenu(f.figure_id,gettext('File'))
delmenu(f.figure_id,gettext('?'))
delmenu(f.figure_id,gettext('Tools'))
toolbar(f.figure_id,'off')
//Cabinet - TEXT
handles.obj17=uicontrol(f,'unit','normalized','BackgroundColor',[1,1,1],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[12],'FontUnits','points','FontWeight','normal','ForegroundColor',[0,0,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.15,0.93,0.1,0.05],'Relief','flat','SliderStep',[0.01,0.1],'String','Cabinet','Style','text','Value',[0],'VerticalAlignment','middle','Visible','on','Tag','obj17','Callback','')
// Cabinet - POP UP MENU
handles.service=uicontrol(f,'unit','normalized','BackgroundColor',[0.8,0.8,0.8],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[12],'FontUnits','points','FontWeight','normal','ForegroundColor',[0,0.5,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.25,0.93,0.15,0.05],'Relief','flat','SliderStep',[0.01,0.1],'String','1|2','Style','popupmenu','Value',[1],'VerticalAlignment','middle','Visible','on','Tag','service','Callback','service_callback(handles)')
// CALCULATE PUSHBUTTON
handles.Calculate=uicontrol(f,'unit','normalized','BackgroundColor',[0,0.8,0],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[16],'FontUnits','points','FontWeight','bold','ForegroundColor',[0,0,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.22,0.02,0.15,0.08],'Relief','raised','SliderStep',[0.01,0.1],'String','CALCULATE','Style','pushbutton','Value',[0],'VerticalAlignment','middle','Visible','on','Tag','Calculate','Callback','Calculate_callback(handles)')
// Resources- TEXT
handles.Resourcestxt=uicontrol(f,'unit','normalized','BackgroundColor',[1,1,1],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[14],'FontUnits','points','FontWeight','bold','ForegroundColor',[0,0.5,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.75,0.95,0.20,0.05],'SliderStep',[0.01,0.1],'String','Resources in hours','Style','text','Value',[0],'VerticalAlignment','middle','Visible','on','Tag','','Callback','')
// TOTAL hours - TEXT
handles.totalhourstxt=uicontrol(f,'unit','normalized','BackgroundColor',[1,1,1],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[14],'FontUnits','points','FontWeight','bold','ForegroundColor',[0,0.5,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.75,0.75,0.12,0.05],'SliderStep',[0.01,0.1],'String','Total Hours','Style','text','Value',[0],'VerticalAlignment','middle','Visible','on','Tag','','Callback','')
// hardware hours - text
handles.totalhours=uicontrol(f,'unit','normalized','BackgroundColor',[0.95,1,1],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[14],'FontUnits','points','FontWeight','bold','ForegroundColor',[0,0.5,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.88,0.75,0.08,0.05],'SliderStep',[0.01,0.1],'String','','Style','text','Value',[0],'VerticalAlignment','middle','Visible','on','Tag','totalhours','Callback','')
function Calculate_callback(handles)
if handles.service.value == 1 then
resource_hrs = 2
end
if handles.service.value == 2 then
resource_hrs = 10
end
set(handles.totalhours,'String',string(resource_hrs));
endfunction

Problem
It is a scoping problem. When function exam_callback() gets called it runs the other script with exec('costs0-1.sce',-1).
In that script you define the function Calculate_callback(handles). This goes out of scope and is deleted when exam_callback() is finished and as such can't be called when the button is pressed.
The second problem is that the handles are not globally affected, so when leaving exam_callback() the handles of the second Cost Gui are not added to handles.
Solution
You can move the generating of the GUI into a function createCostGui() and then load script2 at the start of script1 with exec('costs0-1.sce',-1);.
To make Calculate_callback(handles) function discard the handles argument and use the tags to find the handles
function Calculate_callback()
serviceHandle = findobj('tag','service');
if serviceHandle.value == 1 then
resource_hrs = 2
end
if serviceHandle.value == 2 then
resource_hrs = 10
end
totalHoursHandle = findobj('tag','totalhours');
set(totalHoursHandle,'String',string(resource_hrs));
endfunction
Further remarks
Text elements are generally static and thus don't need a Callback argument.
If you want an argument to stay at its default value, you don't need to specify them.
From the Scilab documentation:
h = uicontrol(PropertyName, PropertyValue,...) creates an uicontrol and assigns the specified properties and values to it. It assigns the default values to any properties you do not specify. The default uicontrol style is a "Pushbutton". The default parent is the current figure. See the Properties section for information about these and other properties.
Small remark on your question
Next time an error message could help with making your question more specific.

Related

onClick is always returning 25

I'm using reactjs.
I have a series of divs that are created that represent a employee's availability. When clicked, they will display the number. However, they all alert the number 25 instead of their number.
for (
var i = state.availability[day][0];
i <= state.availability[day][1];
i++
) {
tempdaySlot.push(
<div
key={"ena:" + TimeConverter(i)}
style={LocalStyles.daySlot}
onClick={() => alert(i)}
>
{TimeConverter(i)}
</div>
);
}
state.availability is a two dimensional array that holds a number between 1-24 that represents someone's availability (ex [9-17])
TimeConverter is a function that converts a 24 hour type number to the usual 12 hour format (17 = "5 pm")
tempdaySlot is just a temporary array before I put it into a state variable
Use let i instead of var i. var hoists variable to the parent scope, let creates block scope.
this is a hoisting issue, because you defined the i using var it will be hoisted to the top of the function body so the last value which is 25 will be the only thing stored in that variable and since the variable isn't destroyed because it's hoisted it will only show the latest value.
just use let instead of var its a good practice to use let and const instead of var now so try getting used it, it will save you a lot of headaches.
Tl;dr declare i using let, not var
The var keyword creates variables with function scope. However, when you create a closure (like your onClick function), the lexical environment is captured by reference. When you call that onClick function later, it gets the current value of i (which is 25, since that's where the loop stopped), not the value of i when you created the function.
The let keyword creates i with traditional scoping, so in effect a new i is created on each iteration of the loop which solves this problem.
See What's the difference between using "let" and "var"? for more.

Is there a way of manipulating a global variable you use as an argument for a function in lua?

I'm trying to write some code into a function so that it can be easily reused whereby a global value is increased.
The issue is that there are several different globals that can be manipulated, and I need the function to be able to handle each one.
I thought I could simply put the global variable into the argument in the function but it doesn't seem to work. Probably because lua creates a copy of the global variable it takes.
Is there a way to make sure that the global variable it manipulates is not just a copy?
I have already tried to make sure that all the relevant variables remain local, but the problem is that they are all in a loop, and so need to remain outside the loop to be able to increment properly.
Right now I have to write a separate function for each case of incrementation which is a little unweildy, if bareable.
Right now I have to do something like this
foo_time_1 = 0
foo_time_2 = 0
function foo_time_1(var)
foo_time_1 += 2
if foo_time < 2 then
sfx(02)
end
end
function foo_time_2(var)
if foo_time_2 < 2 then
sfx(02)
end
end
This allows the code to run as intended, but Ideally I would like the code to look something like this:
foo_time = 0
foo_time_2 = 0
function foo_time_manipulator(global_var, len, sfx)
global_var += 2
if global_var < len then
play(sfx)
end
end
//so I can write
foo_time_manipulator(foo_time, 2, 02)
foo_time_manupulator(foo_time_2, 3, 02)
The problem with that is that the global variable doesn't change and so the sound effect loops continuously as every frame the function is re-read and it see that the global varaible remains at the value it was used as an argument, rather than the updated variable.
Sorry if this question has been poorly worded, it's a little difficult to articulate.
Is there any way in lua to be able to manipulate a global variable that is used as an argument?
A good qualifier may be that this code is being looped, and so requires an outside variable to act as a counter.
You can try this:
function foo_time_manipulator(global_var_name, len, six)
local global_var = _G[global_var_name]
global_var = global_var + 2
if global_var < len then
play(sfx)
end
end
and use it like this
foo_time_manipulator("foo_time", 2, 02)
foo_time_manupulator("foo_time_2", 3, 02)

Error : 'x' undefined

I got a problem with running Octave function (ODE), I've tried already present solutions for this problem but nothing is working. I've also tried by saving my filename as egzamin.m but it too not worked.
Code from octave :
function dx=egzamin(x,t)
dx=zeros(4,1);
b=0;
g=9.81;
x1=x(1);
y1=x(2);
Vx=x(3);
Vy=x(4);
dx(1)=Vx;
dx(2)=Vy;
dx(3)=-b*Vx*sqrt(Vx.^2+Vy.^2);
dx(4)=-b*Vy*sqrt(Vx.^2+Vy.^2)-g;
endfunction
N=mod(291813,100);
x1=0;
y1=0;
Vx=20+N;
Vy=20+N;
t=0:0.01:500;
sol=lsode("egzamin",[x1,y1,Vx,Vy],t);
plot(sol(:,1),sol(:,2))
The error is :
error: 'x' undefined near line 5 column 4
error: called from
egzamin at line 5 column 3
Since the file starts with function, it is not a script file,
as explained in the doc:
Unlike a function file, a script file must not begin with the keyword
function
Add any statement (even dummy like 1;) before the function line to get a script file.
# dummy statement to get a script file instead of a function file
1;
function dx=egzamin(x,t)
g = 9.81;
Vx = x(3);
Vy = x(4);
dx = [Vx, Vy, 0, -g];
endfunction
N=mod(291813,100);
x1=0;
y1=0;
Vx=20+N;
Vy=20+N;
t=0:0.01:500;
sol=lsode("egzamin",[x1,y1,Vx,Vy],t);
plot(sol(:,1),sol(:,2))
A very clear explanation of what's going on is given here.
You need to save the function (thus from function to endfunction and naught else) as egzamin.m, and then execute the rest of the code in a script or at the command line. Alternatively, provided Octave does that the same as what MATLAB does nowadays, first put your script (N=(..) to plot()) and then the function.
This is necessary since you are defining your function first, so it doesn't have any inputs yet, as you don't define them until later. The function needs to have its inputs defined before it executes, hence you need to save your function separately.
You can of course save your "script" bit, thus everything which is currently below your function declaration, as a function as well, simply don't give it in- and outputs, or, set all the input parameters here as well. (Which I wouldn't do as it's the same as your
egzamin then.) e.g.
function []=MyFunc()
N=mod(291813,100);
x1=0;
y1=0;
Vx=20+N;
Vy=20+N;
t=0:0.01:500;
sol=lsode("egzamin",[x1,y1,Vx,Vy],t);
plot(sol(:,1),sol(:,2))
endfunction

How do I set a function to a variable in MATLAB

As a homework assignment, I'm writing a code that uses the bisection method to calculate the root of a function with one variable within a range. I created a user function that does the calculations, but one of the inputs of the function is supposed to be "fun" which is supposed to be set equal to the function.
Here is my code, before I go on:
function [ Ts ] = BisectionRoot( fun,a,b,TolMax )
%This function finds the value of Ts by finding the root of a given function within a given range to a given
%tolerance, using the Bisection Method.
Fa = fun(a);
Fb = fun(b);
if Fa * Fb > 0
disp('Error: The function has no roots in between the given bounds')
else
xNS = (a + b)/2;
toli = abs((b-a)/2);
FxNS = fun(xns);
if FxNS == 0
Ts = xNS;
break
end
if toli , TolMax
Ts = xNS;
break
end
if fun(a) * FxNS < 0
b = xNS;
else
a = xNS;
end
end
Ts
end
The input arguments are defined by our teacher, so I can't mess with them. We're supposed to set those variables in the command window before running the function. That way, we can use the program later on for other things. (Even though I think fzero() can be used to do this)
My problem is that I'm not sure how to set fun to something, and then use that in a way that I can do fun(a) or fun(b). In our book they do something they call defining f(x) as an anonymous function. They do this for an example problem:
F = # (x) 8-4.5*(x-sin(x))
But when I try doing that, I get the error, Error: Unexpected MATLAB operator.
If you guys want to try running the program to test your solutions before posting (hopefully my program works!) you can use these variables from an example in the book:
fun = 8 - 4.5*(x - sin(x))
a = 2
b = 3
TolMax = .001
The answer the get in the book for using those is 2.430664.
I'm sure the answer to this is incredibly easy and straightforward, but for some reason, I can't find a way to do it! Thank you for your help.
To get you going, it looks like your example is missing some syntax. Instead of either of these (from your question):
fun = 8 - 4.5*(x - sin(x)) % Missing function handle declaration symbol "#"
F = # (x) 8-4.5*(x-sin9(x)) %Unless you have defined it, there is no function "sin9"
Use
fun = #(x) 8 - 4.5*(x - sin(x))
Then you would call your function like this:
fun = #(x) 8 - 4.5*(x - sin(x));
a = 2;
b = 3;
TolMax = .001;
root = BisectionRoot( fun,a,b,TolMax );
To debug (which you will need to do), use the debugger.
The command dbstop if error stops execution and opens the file at the point of the problem, letting you examine the variable values and function stack.
Clicking on the "-" marks in the editor creates a break point, forcing the function to pause execution at that point, again so that you can examine the contents. Note that you can step through the code line by line using the debug buttons at the top of the editor.
dbquit quits debug mode
dbclear all clears all break points

MATLAB How to pass an Array from my base workspace to a function

I have been on a few forum posts now reading through trying to figure this out but I can't seem to crack it. To summarise my function I have 2 arrays searchDates and searchIds. Now all I want to do is do a comparison on the size of one of the elements to the other array and this is the code I have so far but I don't know how to carry over searchDates and searchIds
function a = compare(userNum)
if size(searchDates{1,userNum},2) == size(searchIds{1,userNum},2)
x = true
else x = false
end
TL;DR I just need to know how to pass from my BASE WORKSPACE to my FUNCTION WORKSPACE the two arrays from above.
Cheers!
You can rewrite your function so that you can directly pass the arrays:
function a = compare(userNum,searchDates,searchIds)
if size(searchDates{1,userNum},2) == size(searchIds{1,userNum},2)
x = true
else x = false
end
then call compare with your workspace variables in the 2nd and 3rd argument.
If for some reason you need compare to only have one argument, you can create an anonymous function in your workspace by using the above function compare and writing:
anon_compare = #(userNum) compare(userNum,searchDates,searchIds)
Provided searchDAtes and searchIds are in your workspace, you will now have the function anon_compare, which you can use directly as anon_compare(foo).
For more on anonymous functions (an important aspect of several MATLAB programming techniques) you can read this post.