Defining relationship for symbolic variable in MATLAB - matlab

Let's say I have a symbolic variable "q" that depends on another symbolic variable "t".
This is how I define each symbolic variables.
t= sym('t');
q = sym('q(t)');
And I have an expression that contains this (when I use pretty(expression))
result = blah1* diff(q(t),t) *blah2
I want to make this particular part a new variable. Let's say "qdot"
In the end, I want it to be like this.
result2 = blah1*qdot*blah2
I'm in the process of figuring it out. Thank you in advance.

You should use the subs function. Here is how to use it for your particular question
function Rewrite()
t = sym('t');
q = sym('q(t)');
a = sym('a');
blah1 = a^2;
blah2 = t^3;
result1 = blah1*diff(q,t)*blah2;
qDot = sym('qDot');
result2 = subs(result1, diff(q,t), qDot)
% result2 = a^2*qDot*t^3;
end
Note that
result2 = subs(result1, 'diff(q(t),t)', qDot)
and
newMiddle = sym('qDot');
result2 = subs(result1, diff(q,t), newMiddle)
also give the desired result.

Related

concatenation of the arrayfun output

Assuming that
outputTemp =
2×1 cell array
{122×1 string}
{220×1 string}
finalOutput is a string array (342x1 string).
is there any way to do the following
outputTemp = arrayfun(#(x)someFunc(x), someInput, 'UniformOutput', false)';
finalOutput= [outputTemp{1}; outputTemp{2}];
in one line?
for the minimal example, someFunc can be a function that provides the names of the files in folders provided in someInput.
Short answer: yes. Here is a MWE:
str1 = ["Test";"Test1";"42"]
str2 = ["new test";"pi = 3"]
C = {str1;str2}
ConCatStr = [C{1};C{2}];
This should answer the question regarding concatnation of string-arrays. Note that this is only possible with real strings (not with char-arrays). It is hard to tell, what you are doing beforehand as there are not details about getFilesFilt() and mainFolderCUBX.
EDIT MVE for the updated question
% function that returns a matrix
fnc = #(x)[x,1];
% anonymous function that returns a vector
fnc2 = #(x)reshape(fnc(x),2,1)
tmp = arrayfun(#(x)fnc(x), rand(10,1),'UniformOutput',false)
Answer: there is no proper way. However, you can do a little bit of fiddling and force everything into a single line (making the code ugly and less efficient)
tmp = arrayfun(#(x)fnc(x), rand(10,1),'UniformOutput',false);
out = reshape(cell2mat(tmp),numel(cell2mat(tmp)),1);
just replace the tmp with what is written with it.
You can try the following code using cat() + subsref(), i.e.,
finalOutput= cat(1,subsref(arrayfun(#(x)someFunc(x), someInput, 'UniformOutput', false),struct('type', '{}', 'subs', {{:}})));
Example
S(1).f1 = rand(3,5);
S(2).f1 = rand(6,10);
S(3).f1 = rand(4,2);
cat(1,subsref(arrayfun(#(x) mean(x.f1)',S,'UniformOutput',false),struct('type', '{}', 'subs', {{:}})))
such that
ans =
0.89762
0.53776
0.42440
0.25272
0.58197
0.34503
0.40259
0.41792
0.43527
0.53974
0.49976
0.63342
0.36539
0.58541
0.57042
0.60914
0.60851

MATLAB: How to dynamically access variables

I declared some variables comprising of simple row vectors which represents input parameters for another function. Within a loop these variables should be used and the result will be assigned to a structure.
Now, my question is how to best access the content of the predefined variables. I found a solution using eval. However, I often read that the usage of eval should be avoided. Apparently it's not best practice. So, what's best practice for my problem?
varABC = [1,2,3];
varDEF = [4,5,6];
varGHI = [7,8,9];
names = {'ABC','DEF','GHI'};
result = {'result1','result2','result3'};
for i = 1 : 3
varString = strcat('var',names{i});
test.(result{i}) = sum(eval(varString));
end
I would suggest rewriting your code a little bit
names = {'ABC','DEF','GHI'};
result = {'result1','result2','result3'};
option 1
% Use struct instead of a simple variable
var.ABC = [1,2,3];
var.DEF = [4,5,6];
var.GHI = [7,8,9];
for i = 1 : 3
test.(result{i}) = sum(var.(names{i}));
end
option 2
% Use dictionary
c = containers.Map;
c('ABC') = [1,2,3];
c('DEF') = [4,5,6];
c('GHI') = [7,8,9];
for i = 1 : 3
test.(result{i}) = sum(c(names{i}));
end

Use of if statement in for loop in this code

What does the statement for if=ilow:ihigh mean in this program?
function [d]=for_taup(m,dt,h,q,N,flow,fhigh);
nt= max(size(m));
nh = max(size(h));
M = fft(m,[],1);
D = zeros(nt,nh);
i = sqrt(-1);
ilow = floor(flow*dt*nt)+1; if ilow<1; ilow=1;end;
ihigh = floor(fhigh*dt*nt)+1;
if ihigh>floor(nt/2)+1; ihigh=floor(nt/2)+1;end
for if=ilow:ihigh
f = 2.*pi*(if-1)/nt/dt;
L = exp(i*f*(h.^N)’*q);
x = M(if,:)’;
y = L * x;
D(if,:) = y’;
D(nt+2-if,:) = conj(y)’;
end
D(nt/2+1,:) = zeros(1,nh);
d = real(ifft(D,[],1));
return;
if is used as a variable name. I am surprised that this does not raise a syntax error: most languages would forbid the use of "reserved" keywords. Maybe it would be a good idea to replace if with a different name in order to clarify your code and avoid confusion.
As far as MATLAB is concerned, this code doesn't really mean anything, because it's just a syntax error. if is reserved keyword, and you can't create a variable called if. As such, it just instantly errors and won't run.
You should probably replace all occurrences of the variable if (although not the keyword if in lines 8 and 10) with some other variable name. Avoid i, since you're using that as the imaginary unit.

MATLAB - Cleanly read variables out of a function possibly using some type of varargout...?

I have function f1 which must contain subfunctions, so I can't use another script:
function vars = f1()
a = 1;
b = 'hello';
c = {[1 2 3]};
currvars = whos; %all variable info
for k = 1:size(currvars, 1)
eval(['vars.(currvars(k).name) = ' currvars(k).name ';']);
end
end
I call the function in a script, and then I create the variables in the script using genvarname() and eval():
vars = f1();
varnames = genvarname(fieldnames(vars));
for k = 1:size(varnames(:),1) %Creates vars with the struct's fieldnames.
eval([varnames{k} ' = vars.' varnames{k} ';']);
end
clearvars vars varnames
I'd like to fit the variable creation process into a function somehow while reading out all the variables only to the script calling it, but I don't want to assign a hundred different variable names to the output. Does anyone have any advice on how to do this?
DON'T CREATE zillions of automatically named variables. This is foolish and terribly poor programming style. Instead, learn to use arrays. Multidimensional arrays, cell arrays, struct arrays.
Or, do what you have done, and then be forced to find a kludge like you are looking for.
Take your pick. Eval is evil.
You could return a structure with "corrected" fieldnames:
function output = someFunc
vars = f1();
protected = { %# some list of varnames you don't want
};
names = fieldnames(vars);
newnames = genvarname(names, protected);
for k = 1:numel(newnames)
output.(newnames{k}) = vars.(names{k});
end
end
If you then use
output = someFunc;
varnames = fieldnames(output);
for k = 1:numel(fieldnames)
eval([varnames{k} ' = output.' varnames{k} ';']);
end
in the script/function where you want the variable names, you have a relatively clean way of locking everything up in the function someFunc without having to pre-define all output variable names.
You can also do this in one step:
function someFunc2
vars = f1();
protected = { %# some list of varnames you don't want
};
names = fieldnames(vars);
newnames = genvarname(names, protected);
for k = 1:numel(newnames)
assignin('caller', newnames{k}, vars.(names{k}));
end
end
Which means you just call the function
someFunc2;
in your script, and the function then defines and assigns all the variables in the script's workspace.
A tiny step forward, but forward nonetheless :)
CREDIT TO RODY...
#Old semi-"global" variables:
function vars = f1()
a = 1;
b = 'hello';
c = {[1 2 3]};
currvars = whos; %all variable info
for k = 1:size(currvars, 1)
eval(['vars.(currvars(k).name) = ' currvars(k).name ';']);
end
end
#Function to assign variables to the calling script's/function's workspace. Variable names are determined by the single structure's fieldnames:
function setvars(func)
vars = func;
protected = {'If needed, put variable names you do not want here'};
names = fieldnames(vars);
newnames = genvarname(names, protected);
for k = 1:numel(newnames)
assignin('caller', newnames{k}, vars.(names{k}));
end
end
#Script call:
setvars(f1);

How do I rename a field in a structure array in MATLAB?

Given a structure array, how do I rename a field? For example, given the following, how do I change "bar" to "baz".
clear
a(1).foo = 1;
a(1).bar = 'one';
a(2).foo = 2;
a(2).bar = 'two';
a(3).foo = 3;
a(3).bar = 'three';
disp(a)
What is the best method, where "best" is a balance of performance, clarity, and generality?
Expanding on this solution from Matthew, you can also use dynamic field names if the new and old field names are stored as strings:
newName = 'baz';
oldName = 'bar';
[a.(newName)] = a.(oldName);
a = rmfield(a,oldName);
Here's a way to do it with list expansion/rmfield:
[a.baz] = a.bar;
a = rmfield(a,'bar');
disp(a)
The first line was originally written [a(:).baz] = deal(a(:).bar);, but SCFrench pointed out that the deal was unnecessary.
Here's a a way to do it with struct2cell/cell2struct:
f = fieldnames(a);
f{strmatch('bar',f,'exact')} = 'baz';
c = struct2cell(a);
a = cell2struct(c,f);
disp(a)