How to insert a structure into a function in matlab - matlab

I am writing a matlab function as :
function [resultNorm]= explorEffort (n, loop, step)
...
Somelines
...
M=bench(a,b).Y ;
end
but it seems that the matlab compiler doesn't let me use a structure in the function, the error is:
Error: File: explorEffort.m Line: 20 Column: 15
Functions cannot be indexed using {} or . indexing.
P.S: the bench definition
bench =
24x5 struct array with fields:
application
dataset
mica
micaNorm
DB
Y
Could anyone mention how am I gonna be able to fix that?

Method-1
There is a possibility to define the structure (namely here, bench) as global outside the file and just call global bench; right before the first appearance of the bench.
Method-2
the safer choice could be passing the structure among the input argument of the function as :
function [resultNorm]= explorEffort (n, loop, step, `bench`)
in this case no need to prior unnecessary globalization.

I believe the main issue was that "bench" is a MATLAB builtin(depending on your version of matlab).
You can try renaming your variable in the future.
you can run :
X=bench; or help bench
I run into similar issue before.

Related

Is it possible to use fsolve if an existing script return a class structure?

I have a script Function.m such that for example, when I write TEST=Function(1,2), I have TEST.x1=4 and TEST.x2=[5,6,7]. I want to use fsolve to help me find input. To be precise, I want to define a function, say a=#(y)Function(1,y)-4 so that when I use [z,vector]=fsolve(#(y)a(y),5), matlab can help me to obtain z=2 and vector=[5,6,7].
I would like to solve it by defining the same structure New_Function.m as Function.m such that it returns x1 values, i.e., TEST=New_Function(1,2) gives TEST=4 only. Then I write new_a=#(y)New_Function(1,y)-4 and solve z=fsolve(#(y)new_a(y),5) and define new_vector=Function(1,z) so that I can access new_vector.x2.
I want to know if it is possible to do my task without defining a new script or amending the content in the existing script. How to write code?
Since Matlab does not allow further referencing the result of a function call, you may need to help yourself with getfield. In your example (provided I got it right), it would be something like New_Func = #(y) getfield(Function(1,y),'x1'). This would take one scalar and return one scalar, i.e., New_Func(y) gives the field value of the struct returned by Function(1,y) associated to the field x1.

equivalent of `evalin` that doesn't require an output argument (internally)

Background -- I was reading up on accessing shadowed functions, and started playing with builtin . I wrote a little function:
function klear(x)
% go to parent environment...
evalin('base', builtin('clear','x')) ;
end
This throws the error:
Error using clear
Too many output arguments.
I think this happens because evalin demands an output from whatever it's being fed, but clear is one of the functions which has no return value.
So two questions: am I interpreting this correctly, and if so, is there an alternative function that allows me to execute a function in the parent environment (that doesn't require an output)?
Note: I'm fully aware of the arguments against trying to access shadowed funcs (or rather, to avoid naming functions in a way that overload base funcs, etc). This is primarily a question to help me learn what can and can't be done in MATLAB.
Note 2
My original goal was to write an overload function that would require an input argument, to avoid the malware-ish behavior of clear, which defaults to deleting everything. In Q&D pseudocode,
function clear(x)
if ~exist('x','var') return
execute_in_base_env(builtin(clear(x)))
end
There's a couple issues with your clear override:
It will always clear in the base workspace regardless of where it's called from.
It doesn't support multiple inputs, which is a common use case for clear.
Instead I'd have it check for whether it was called from the base workspace, and special-case that for your check for whether it's clearing everything. If some function is calling plain clear to clear all its variables, that's bad practice, but it's still how that function's logic works, and you don't want to break that. Otherwise it could error, or worse, return incorrect results.
So, something like this:
function clear(varargin)
stk = dbstack;
if numel(stk) == 1 && (nargin == 0 || ismember('all', varargin))
fprintf('clear: balking at clearing all vars in base workspace. Nothing cleared.\n');
return;
end
% Check for quoting problems
for i = 1:numel(varargin)
if any(varargin{i} == '''')
error('You have a quote in one of your args. That''s not valid.');
end
end
% Construct a clear() call that works with evalin()
arg_strs = strcat('''', varargin, '''');
arg_strs = [{'''clear'''} arg_strs];
expr = ['builtin(' strjoin(arg_strs, ', '), ')'];
% Do it
evalin('caller', expr);
end
I hope it goes without saying that this is an atrocious hack that I wouldn't recommend in practice. :)
What happens in your code:
evalin('base', builtin('clear','x'));
is that builtin is evaluated in the current context, and because it is used as an argument to evalin, it is expected to produce an output. It is exactly the same as:
ans = builtin('clear','x');
evalin('base',ans);
The error message you see occurs in the first of those two lines of code, not in the second. It is not because of evalin, which does support calling statements that don't produce an output argument.
evalin requires a string to evaluate. You need to build this string:
str = 'builtin(''clear'',''x'')';
evalin('base',ans);
(In MATLAB, the quote character is escaped by doubling it.)
You function thus would look like this:
function clear(var)
try
evalin('base',['builtin(''clear'',''',var,''')'])
catch
% ignore error
end
end
(Inserting a string into another string this way is rather awkward, one of the many reasons I don't like eval and friends).
It might be better to use evalin('caller',...) in this case, so that when you call the new clear from within a function, it deletes something in the function's workspace, not the base one. I think 'base' should only be used from within a GUI that is expected to control variables in the user's workspace, not from a function that could be called anywhere and is expected (by its name in this case) to do something local.
There are reasons why this might be genuinely useful, but in general you should try to avoid the use of clear just as much as the use of eval and friends. clear slows down program execution. It is much easier (both on the user and on the MATLAB JIT) to assign an empty array to a variable to remove its contents from memory (as suggested by rahnema1 in a comment. Your base workspace would not be cluttered with variables if you used function more: write functions, not scripts!

Matlab permutation

I have written a function to perform permutations of n obejects.
I have the variables a=[1],[2],[3];k=1 and n=4;a contains the objects which are 1,2 and 3 respectively.The following is the function code that i have written:
function [res]=perm(a,k,n,jj)
if k==n
res{jj}=a;
jj=jj+1;
else
for i=k:n
t=a{k};
a{k}=a{i};
a{i}=t;
perm(a,k+1,n,jj)
t=a{k};
a{k}=a{i};
a{i}=t;
end
end
end
However, when i call the function as:
jj=1;
[res]=perm(a,k,n,jj)
I am getting the following error displayed:
Error in ==> perm at 3
if k==n
??? Output argument "res" (and maybe others) not assigned during call to "J:\main
project\perm.m>perm".
Error in ==> mainp at 254
[res]=perm(a,k,n,jj)
The following is the code in the main program with regard to the permutation:
mr=4
for i=1:mr
a{i}=i;
end
n=mr;
%This assignment is for the ease to work with.
%just stored the indices till mr for the purpose of permutation
k=1;
%this is the k that the function perm has
jj=1;
[res]=perm(a,k,n,jj)
Can somebody please help me resolve this?Thanks in advance.
Your else block leaves res undefined.
I think you're assuming that res is a global variable and all invocations of perm will write into different parts of a single cell array. That isn't true. It is an output variable, local to the current call. There's no sharing during recursion, they all have independent cell arrays named res. The parameter jj is also not shared, so adding one is useless as well.
If you want to use this technique of building up the output, you'll need to make sure it is defined at a wider scope than the recursion. For example, use a local helper function:
function [res]=perm(a,k,n,jj)
res = {};
perm_impl(a,k);
function [] = perm_impl(a,k) // doesn't get its own local res, n, or jj
if k==n
res{jj}=a;
jj=jj+1;
else
for i=k:n
t=a{k};
a{k}=a{i};
a{i}=t;
perm_impl(a,k+1)
t=a{k};
a{k}=a{i};
a{i}=t;
end
end
end
end
Now all runs of perm_impl work on the same cell array res, because Matlab documentation says:
Variables within nested functions are accessible to more than just their immediate function. A variable, x, to which you assign a value or use within a nested function resides in the workspace of the outermost function that both contains the nested function and accesses x.
If you intentionally use a variable in this manner, it is not a problem. For examples, see the MATLAB Programming Demo on Nested Functions.
However, if you unintentionally use a variable in this manner, it can result in unexpected behavior. If the highlighting indicates that the scope of a variable spans multiple functions, and that was not your intent, consider:
Renaming the nested function variable so it does not match the outer function variable name.
Passing the variable into the function as an input argument instead of using the variable directly within the nested function
I can't tell whether a was supposed to be shared or not...

Working with different version of Matlab Function

We have a legacy definition of a matlab function nanstd.m which is being called in a whole lot of functions.
The legacy version has definition like:
function y = nanstd(x, dim);
The above definition is stored on our local server drive "H\Util\Functions".
The newer version of matlab has a differetn definition which is:
function y = nanstd(fts, varargin)
The above translates to:
Y = nanstd(X,flag,dim)
The above is stored under "C\Program Files\Matlab".
We need both versions to be available. Is it possible that I can write a code which says something like if there are 2 arguments input use nanstd.m at "H\Util\Functions" and if there are 3 inputs use nanstd.m at "C\Program Files\Matlab".
Thanks
Since your legacy definition should come before the builtin version on your path, you could simply add the following to your custom nanstd so it behaves as follows:
function y = nanstd(x,varargin)
if nargin > 2
wd = cd(fullfile(matlabroot,'toolbox','stats','stats'));
y = nanstd(x,varargin{:});
cd(wd)
return
elseif nargin == 2
flag = varargin{1};
end
%// ... continue custom nanstd function
As per this discussion on MatlabCentral, the only way to run a shadowed function is to change to its directory. Amazingly enough, the path favors the current directory to the current function — something that surprised me — but it's beneficial for this case. This allows you to simply modify your custom legacy nanstd function to kick out to the builtin definition.
Edit: you may want to wrap the call to the stats nanstd with a try/catch so your directory always gets restored, even in case of an error.
Recommended approach
This is probably the way I would do it (if I didn't want to make a complete mess in the future).
Locate all old files, and replace nanstd( by nanstdold(, this can be automated in many ways.
(If you actually have variables named nanstd you will feel the pain of course)
Then, to be safe define your function as follows:
function y = nanstdold(fts, varargin)
if nargin = 2
y = nanstd(fts,[],varargin)
else
y = nanstd(fts,varargin)
end
You may need to tweak the first call to nanstd, but I think this line of thought should get you there.
Make sure to burn the nanstd function that only takes 2 input arguments, so you cannot accidentally refer to it.
Alternate approach
If you feel confident, you could try to design a replacement rule to automatically update all your old files without introducing a new function. Something to start with:
Find all occurences of
nanstd( + something+ comma that is not between {} or ()
And replace them with
nanstd( + something+ comma + flag argument + comma
Especially for this one you will want to back up your files first!

matlab: is there a way to import/promote variables from a structure to the current workspace?

function y = myfunc(param)
C = param.C;
L = param.L;
Kp = param.Kp;
Ki = param.Ki;
...
Is there a way to generalize the above code? I know how to generalize the structure access using fieldnames() and getfield(), but not how to set variables without calling eval() (which is evil).
for n = fieldnames(param)'
name = n{1};
value = param.(name);
do_something_with(name,value); % ????
never mind, I figured it out; this helper function works:
function vars_pull(s)
for n = fieldnames(s)'
name = n{1};
value = s.(name);
assignin('caller',name,value);
end
The only way to create a variable whose name is determined at run-time is to use a function like eval, evalin, feval, or assignin. (assignin is the least evil choice BTW, at least you don't need to convert your value to a string and back.)
However, I question why you want to do that, why not just access the values through the input structure as you need them. If you want to save typing (speaking from experience, as I am extremely lazy), I usually name my input parameter structure something short, like p. The throughout my code I just access the fields directly, (e.g. p.Kp, and after a while I don't even see the p. anymore.) This also makes it easy to pass the structure into subfunctions as needed.
You can use the excellent submission at FileExchange:
V2STRUCT - Pack & Unpack variables to & from structures with enhanced functionality
Here's a workaround: save the structure to a .mat file using the '-struct' option, and then immediately reload it. Here's an example for struct variable X:
save('deleteme.mat','-struct','X');
load('deleteme.mat');
delete('deleteme.mat');
It's kludgey, but actually pretty fast, at least with an SSD.