Use MATLAB's 'keyPressFcn' in a simple program - matlab

I am trying to use the 'KeyPressFcn' in a normal MATLAB script, but I am having problems. I can use it nicely WITHIN a function, (like here), but I would like to use it in a normal script like so.
My simple script is:
%Entry Point
clear all
N = 100;
x = randn(1,N);
figHandle = figure(1);
clf(figHandle);
set(figHandle, 'KeyPressFcn', myFunction(~, eventDat,x,N))
Here is the function 'myFunction' that sits in the same directory:
function myFunction(~, eventDat,x,N)
mean = sum(x)/N;
disp(mean);
key = eventDat.Key;
disp(key);
end
Now, if I run this, it does not work, because, (I suspect), something is wrong with the way I am calling myFunction, but I cannot figure out what the problem is exactly, since I am a noob at using KeyPressFcn. Help would be appreciated for this problem. Thanks!

You need to do it through anonymous functions:
In script file, for example called test.m:
%Entry Point
clear all
N = 100;
x = randn(1,N);
figHandle = figure(1);
clf(figHandle);
set(figHandle, 'KeyPressFcn', ...
#(fig_obj , eventDat) myFunction(fig_obj, eventDat, x, N));
In a file called myFunction.m in the same folder as test.m
function myFunction(~, eventDat, x, N)
mean = sum(x)/N;
disp(mean);
key = eventDat.Key;
disp(key);
How to return value from myFunction?
There are few ways of doing this. It depends on what u want to do. But quickly you could use mutable variables for this, such as, containers.Map. This is one example of ding this. The returned variable is newN.
In script file, for example called test.m:
%Entry Point
clear all
N = 100;
x = randn(1,N);
% this map will store everything u want to return from myFunction.
returnMap = containers.Map;
figHandle = figure(1);
clf(figHandle);
set(figHandle, 'KeyPressFcn', ...
#(fig_obj , eventDat) myFunction(fig_obj, eventDat, x, N, returnMap));
% wait till gui finishes in this example.
waitfor(figHandle);
newN = returnMap('newN');
% display newN
newN
In a file called myFunction.m:
function myFunction(handle, eventDat, x, N, returnMap)
mean = sum(x)/N;
disp(mean);
key = eventDat.Key;
disp(key);
newN = 435;
returnMap('newN') = newN;

Related

Body of this Matlab function works, but not the function itself (interp1 error)

I've written the following piece of subcode (with parameters commented) for an Euler policy iteration algorithm. When I try to run the body of the function (everything below global) for say, a1 = 1, it works, and returns a scalar. However, when I call the function as euler_diff_test(1), I get an error. (Pasted below)
function diff = euler_diff_test(a1)
%the following comments are example parameters. They are in the global line originally.
% r = 0.2, a = 0.5, y = 1.1, a_grid = linspace(0.5,7,100)
%policy_guess = zeros(2,N);
%policy_guess(1,:) = 0.3*a_grid;
%policy_guess(2,:) = 0.3*a_grid;
% M = zeros(2,2); %M for markov transition kernel
% M(1,1) = p;
% M(2,2) = p;
% M(2,1) = 1-p;
% M(1,2) = 1-p;
% j = 1
global r a y a_grid policy_guess M j;
c = (1+r)*a + y - a1; %consumption formula
if c<=1e-02 %don't care about consumption being negative
diff = 888888888888888888888;
else
policy_func = interp1(a_grid', policy_guess', a1, 'linear');
diff = 1/c - beta*(1+r)*(1 ./ policy_func)*M(j,:)';
end
end
Error Reads:
Any help is much appreciated!
The problem is that you dont understand globals nor how they work!
You seem to be doing something like:
N=100; p=0.1;
r = 0.2, a = 0.5, y = 1.1, a_grid = linspace(0.5,7,100)
policy_guess = zeros(2,N);
policy_guess(1,:) = 0.3*a_grid;
policy_guess(2,:) = 0.3*a_grid;
M = zeros(2,2); %M for markov transition kernel
M(1,1) = p;
M(2,2) = p;
M(2,1) = 1-p;
M(1,2) = 1-p;
euler_diff_test(1)
And this is causing the error you show. Of course it is!
First, you need to learn what a global is and what worskpaces are. Each fucntion has its own worskpace or "scope". That means that only variables defined within the workspace are visible by the function itself.
A global variable is one that exist for all workspaces, and everyone can modify it. You seem to want all those variables defined outside the function, inside your function. But realise! when the variables are defined, they are not global. The function starts, and in its first line, it does only know about the existence of a1. Then, later, you define a bunch of variables as global, that the function did not know about. So what does the function do? just create them empty, for you.
If you want your the variables that you create in the main script scope to be global, you need to declare them as global then, not inside the function. So cut your line global ... from the fucntion, and put it on top of the script where you declare all your variables, i.e. on top of
% here!
N=100; p=0.1;
...
in my example.
Now, the important stuff: Global variables are bad. When you have globals, you don't know who modifies, and its super easy to lost track of what is happening to them, because every function that uses a variable a will modify the global a, so its a pain to debug. Almost no one uses globals because of this. The best way is to pass them to the function as input, i.e. define your function as:
function diff = euler_diff_test(a1,r, a, y, a_grid, policy_guess, M, j)

How to change a script to a function?

I've got a set of data in an excel sheet that I've imported onto MATLAB however there are NaNs within that set of data. I've figured out some code in the main script to replace the NaN's into the wanted values:
max = x(:, 2);
min = x(:, 3);
for j = 1:length(max)
for k = 1:length(min)
if isnan (max(j))
max (j) = ((max(j-1)+max(j+1))/2);
elseif isnan (min(k))
min (k) = ((min(k-1)+min(k+1))/2);
end
end
end
However, I need to be able to turn this code into a user-defined function and call it from the main script instead of having all the calculations on the main script.
I've tried to start making the function:
function [missingmax, missingmin] = missing(max, min)
However, I could not figure the rest out.
function [max_x, min_x] = missing(x)
max_x = x(:, 2);
min_x = x(:, 3);
for jj = 1:length(max_x)
for kk = 1:length(min_x)
if isnan (max_x(jj))
max_x (jj) = ((max_x(jj-1)+max_x(jj+1))/2);
elseif isnan (min_x(kk))
min_x (kk) = ((min_x(kk-1)+min_x(kk+1))/2);
end
end
end
end
You were on the right track. Couple of things:
Your input is x, not min,max
Your outputs are min and max, not missingmax and missingmin
j denotes the imaginary unit It's not recommended for use as a variable, hence I changed it.
You called variables min and max. Don't do that. Ever. Seriously. Don't. If you manage to do min=4 and then try to calculate the minimum of an array, you'll get a bunch of errors. Basically: never use the name of a build-in function for a variable.
Since you do a linear interpolation, you don't need to define a function here. It already exists in Matlab : fillmissing
So you can replace missing values in x like that
x_filled = fillmissing(x,'linear')

Can someone explaine why my function handle does not work?

Newbe here so please don't be too harsh.
I have these three functions, and each has it's own file:
format long
rd = #(x) runden(x,L);
function y = runden(x,L)
y = (round(x*10^L))/10^L;
endfunction
format long
function z = add(x,y,rd)
z = rd(rd(x)+rd(y));
endfunction
format long
function z = mult(x,y,rd)
z = rd(rd(x)*rd(y));
endfunction
as you see I want to use a function handle, so I can use round in the bottom two functions.
The functions have to be in their own files (wasn't a problem so far in matlab).
My Syntax is off, but I can't find a tutorial that handles function handles with two variables.
If I understand, the function handle rd lives only in the first script, and the other scripts can't access it.
If you will name the first file (function) as runden.m, and define rd in the other functions and not in the first one, they will have access to it.
And two notes- don't override preserved function names as add, and use end instead of endfunction.
I would suggest to arrange the functions like that:
% file 1, named `runden.m`
function y = runden(x,L)
format long
y = (round(x*10^L))/10^L;
end
% file 2, named `ad.m`
function z = ad(x,y,L)
format long
rd = #(x) runden(x,L);
z = rd(rd(x)+rd(y));
end
% file 3, named `mult.m`
function z = mult(x,y,L)
format long
rd = #(x) runden(x,L);
z = rd(rd(x)*rd(y));
end

Integrating function with two variables in Matlab

Hey I'm having trouble integrating a function in MATLAB, constantly getting errors. I'm trying to fill a matrix with the function. exp(x-1)*x^j+k
I2 = zeros(26,3);
k = [0.13, 0.0024, 0.000035];
for i = 1:length(k)
for j = 0:25
fun = #(x,j) exp(x-1).*x.^j+k(i);
I2(j,i) = integral(fun,0,1);
end %end j-loop
end %end i-loop
display(I2);
Thanks.
In the current form the function handle is expecting two inputs but you want a function with a single input for integral. Changing your function handle definition to the following should fix this.
fun = #(x) exp(x-1)*x^j+k(i);

First input must be function handle error using arrayfun()

I'm trying to use arrayfun() to map a function over a cell array. The following is happening:
>> arrayfun(solveFunc, equArray)
Error using arrayfun
First input must be a function handle.
Error in solve>genGuess (line 33)
funcVals = abs(arrayfun(inFunc, xValues));
Error in solve (line 8)
x = genGuess(inFunc, varargin{1}, varargin{2});
Error in makeSolveFunc>#(func)solve(func,start,stop) (line 3)
sFunc = #(func) solve(func, start, stop);
But, the first input IS a function handle. Also... if I manually apply the function to each element of the provided cell array, everything works fine:
>> solveFunc(equArray{1})
ans =
4.7335
>> solveFunc(equArray{2})
ans =
4.7356
Does anyone know why this would be happening? I assumed that if I could manually apply the function to each element of my array, and the return type of the function was consistent and one of the allowed types (you can't for example have arrayfun return an array of function handles... I already tried doing that), it should work. Perhaps that is not the only requirement.
Here is some code that generates this error:
solve.m
function solution = solve(inFunc, start, stop)
%SOLVE solve an equation using Newton's Method
x = genGuess(inFunc, start, stop);
for i = 1:100
m = getSlope(inFunc, x);
x = (m*x - inFunc(x))/m;
end
solution = x;
end
function slope = getSlope(inFunc, x)
%SLOPE calculate the slope at a given point
inc = 1e-5;
if x ~= 0
inc = inc * x;
end
slope = (inFunc(x + inc) - inFunc(x - inc))/(2*inc);
end
function guess = genGuess(inFunc, start, stop)
%GENGUESS get an initial guess to the solution
xValues = linspace(start, stop, 101);
funcVals = abs(arrayfun(inFunc, xValues));
[~, minIndex] = min(funcVals);
guess = xValues(minIndex);
end
charEqu.m
function equ = charEqu(a)
%CHAREQU create a KP model characteristic equation with provided p
equ = #(x) x + a;
end
makeSolveFunc.m
function sFunc = makeSolveFunc(start, stop)
%MAKESOLVEFUNC return a function that solves an equation
sFunc = #(func) solve(func, start, stop);
end
test.m
pArray = 1:5;
equArray = cell(1,arrayLen);
for i = 1:5
equArray{i} = charEqu(pArray(i));
end
solveFunc = makeSolveFunc(1.1*pi, 2*pi);
alphaAArray = arrayfun(solveFunc, equArray);
I have narrowed down the error to something in genGuess(). For some reason, in the line funcVals = abs(arrayfun(inFunc, xValues)); the variable inFunc is a 1x1 cell array containing a function handle. I have no idea why that would be the case. I traced this back to the anonymous function call #(func) solve(func, start, stop); in the makeSolveFunc() function. There it is still a 1x1 cell array containing a function handle. I'm not really sure where that cell array is coming from as that function is getting called from arrayfun().
Background information on what I'm trying to do in case someone wants to suggest a better way:
I'm trying to solve equations using Newton's method. I have written a function that can solve an equation given an initial guess range. This function is the solve() function you can see in the first error message. It takes a function, and the guess range and returns a function that I'm calling solveFunc(). solveFunc() takes a function and solves it using the initial guess range previously provided.
Maybe I'm just too used to functional programming and should just use a loop.
If the arguments passed to the function handle are contents of elements of a cell array, you need to use cellfun instead of arrayfun:
cellfun(solveFunc, equArray)
This is equivalent to
for i=1:length(equArray)
out(i) = solveFunc(equArray{i});
end
since solveFunc is already a function handle.
Check where the error comes from. This line causes the error:
funcVals = abs(arrayfun(inFunc, xValues));
The first input argument is a 1x1 cell containing one function handle. This is caused because equArray is a cell, thus use cellfun as Jonas already mentioned:
pArray = 1:5;
equArray = cell(1,arrayLen);
for i = 1:5
equArray{i} = charEqu(pArray(i));
end
solveFunc = makeSolveFunc(1.1*pi, 2*pi);
alphaAArray = cellfun(solveFunc, equArray);