Matlab - With ... End structure - matlab

Does Matlab have a kind of with...end command? http://msdn.microsoft.com/en-us/library/wc500chb(v=vs.80).aspx
I have a variable in my workspace which contains a lot of nested data. Now I don't want to have to type this all the time:
Root.ChildLevel1.A = Root.ChildLevel1.B + Root.ChildLevel1.C
But rather something like:
with Root.ChildLevel1
A = B + C
end
is this possible?

I'm not aware of such functionality in Matlab.
What you can do is
cur = Root.ChildLevel1;
cur.A = cur.B + cur.C;
Edit:
According to comment by #Nick, if Root.ChildLevel1 is not subclass of handle,
then one should add the following line:
Root.ChildLevel1 = cur;
I would also recommend to
clear cur;
at the end.

I have to say that I would not recommend using this function very often, but I once tried a FEX contribution that allows you to unpack structs.
Of course this will still require you to update the struct after you have done the calculations so I only use it for subfunctions that mainly use the struct as input.
I am not sure, but I think this is the one I tried:
http://www.mathworks.com/matlabcentral/fileexchange/26216-structure-fields-to-variables

Related

Only add existing variables in Matlab

I would like to add the sums of 5 one-column arrays in Matlab. The catch is that depending on previous inputs, any of these arrays may or may not exist, thus throwing an error when I try to add the sums of these arrays for post-processing.
After doing some digging I found the following function which I can use to return a logical statement if a certain variable exists in the workspace:
exist('my_variable','var') == 1
I'm not sure this helps me in this case though - Currently the line in which I add the sums of the various arrays looks as follows:
tot_deviation = sum(var1) + sum(var2) + sum(var3) + sum(var4) + sum(var4);
Is there a short way to add only the sums of the existing arrays without excessive loops?
Any help would be appreciated!
You can use if statements:
if ~exist('var1','var'), var1 = 0;end
if ~exist('var2','var'), var2 = 0;end
if ~exist('var3','var'), var3 = 0;end
if ~exist('var4','var'), var4 = 0;end
tot_deviation = sum(var1) + sum(var2) + sum(var3) + sum(var4) + sum(var4);
To my knowledge there is no quick way to do this in matlab. It seems to me that, depending on the structure of your code, you have the following alternatives:
1- Initialize all your variables to column arrays of zeros with something like
var = zeros(nbLines, 1);
2- Put all your columns vectors side to side in a single array and the use tot_deviation = sum(sum(MyArray)); which will work no matter how many columns and lines there is in the array.
3- If you pass your variables to a function you can check the number of inputs arguments inside the function using 'nargin' and then only proceed to sum the right number of variables.
I would recommend using the second method for it seem to me that it is the one that allows you to take the most advantage of matlab's array system which good.
The most robust solution is to initialise all of your variables to 0 at the top of the function. Then there is no chance they don't exist, and they influence the summation correctly.
Alternatively...
You could (read: shouldn't) use a really nasty eval trick here for flexibility...
vars = {'var1','var2','var3','var4'};
tot = 0;
for ii = 1:numel(vars)
if exist(vars{ii}, 'var')
tot = tot + eval(var);
end
end
I say it's "nasty" because eval should be avoided (read the linked blog). The check on the variable name existence mitigates some of the strife, but it's still not ideal.
As suggested in the MathWorks blog on evading eval, a better option would be a struct with dynamic field names. You could use almost the same syntax as above, but replace the if statement with
if isfield( myStruct, vars{ii} )
tot = tot + myStruct.(vars{ii});
end
This will avoid dynamically named variables and keep your workspace clean!

Importing much data to Matlab

I have many .txt files like these: "u1.txt", "i3.txt", "p10.txt"... How to load all of these files to matlab, to variables like these: "u1", "u2"... "p1"... Here is my code:
clc, clear all
%% loading data
for j=0:3
switch j
case 0
variable='i';
case 1
variable='u';
case 2
variable='p';
case 3
variable='q';
end
for i=0:15
name = strcat(variable, int2str(i), '.txt')
fid=fopen(name,'r');
data=textscan(fid,'%*s%*s%s%s%s%*s','HeaderLines',10,'CollectOutput',1);
fclose(fid);
data=strrep(data{1},',','.');
data=cellfun(#str2num, data);
end
end
Problem is with variable data - how to change this variable to: "u1", "u2"... "p1"... after every loop?
You could use the variable names u1 u2 etc.. but I would strongly recommend not to do so. Then these consecutive variables u1 to u15 are totally individual variables and basically matlab can not iterate over these variables. For this purpose, I would use a struct which contains cell arrays. Use this line to assign:
allData.(variable){i}=data
And to get your data, instead of u1 use allData.u{1}. These are some more characters to write, but having such structured data results in much simpler code when you use the data.
//Code:
for j=0:3
switch j
case 0
variable='i';
case 1
variable='u';
case 2
variable='p';
case 3
variable='q';
end
for i=0:15
name = strcat(variable, int2str(i), '.txt')
fid=fopen(name,'r');
data=textscan(fid,'%*s%*s%s%s%s%*s','HeaderLines',10,'CollectOutput',1);
fclose(fid);
data=strrep(data{1},',','.');
data=cellfun(#str2num, data);
allData.(variable){i}=data;
end
end
Use eval.
For example:
x = input('Enter the name of the new variable: ','s');
eval([x,'=0:4;']);
In your case:
variablename = strcat(variable,int2str(i));
eval([variablename,'=cellfun(#str2num,',variablename,')'];
This is a good read: Creating variables on the run
You could use eval to do this:
eval([name '=textscan(fid,'%*s%*s%s%s%s%*s','HeaderLines',10,'CollectOutput',1);']);
I think that syntax is correct but I'm not sure. You might have to play around with it a bit to get it to work, which is a huge drawback to using eval in the first place. Not to mention the syntax parser can't work with it, making it more difficult to debug.
My recommendation would be to utilize MATLAB's capability to use dynamic fieldnames.
data.(name)=textscan(fid,'%*s%*s%s%s%s%*s','HeaderLines',10,'CollectOutput',1);
Much cleaner and much easier to debug.
My other recommendation is that you evaluate why you need to utilize this naming scheme in the first place. It will be much easier to create an array (numeric or cell) and use that numeric ID as an index rather than include it with the variable name.

Debugging a for loop in matlab

I've been looking throught the documentation, but can't seem to find the bit I want.
I have a for loop and I would like to be able to view every value in the for loop.
for example here is a part of my code:
for d = 1 : nb
%for loop performs blade by blade averaging and produces a column vector
for cc = navg : length(atbmat);
atb2 = (sum(atbmat((cc-(navg-1):cc),d)))/navg;
atbvec2(:,cc) = atb2;
end
%assigns column vector 'atbvec2' to the correct column of the matrix 'atbmat2'
atbmat2(d,1:length(atbvec2)) = atbvec2;
end
I would like to view every value of atb2. I'm a python user(new to MATLAB) and would normally use a simple print statement to find this.
I'm sure there is a way to do it, but I can't quite find how.
Thankyou in advance.
you can use disp in Matlab to print to the screen but you might want to use sprintf first to format it nicely. However for debugging you're better off using a break point and then inspect the variable in the workspace browser graphically. To me, this is one of Matlab's best features.
Have a look at the "Examine Values" section of this article
The simplest way to view it everywhere is to change this line:
atb2 = (sum(atbmat((cc-(navg-1):cc),d)))/navg;
Into this, without semicolon:
atb2 = (sum(atbmat((cc-(navg-1):cc),d)))/navg
That being said, given the nature of your calculation, you could get the information you need as well by simply storing every value of abt2 and observing them afterwards. This may be done in atbmat2 already?
If you want to look at each value at the time it happens, consider setting a breakpoint or conditional breakpoint after the line where abt2 is assigned.

How to rename a variable in a loop in MATLAB?

Can somebody please tell if there exists a way to rename a variable in each iteration of a loop in MATLAB?
Actually, I want to save a variable in a loop with a different name incorporating the index of the loop. Thanks.
Based on your comment, I suggest using a cell array. This allows any type of result to be stored by index. For example:
foo=cell(bar,1);
for ii=1:bar
foo{ii}=quux;
end
You can then save foo to retain all your intermediate results. Though the loop index is not baked into the variable name as you want, this offers identical functionality.
Ignoring the question, "why do you need this?", you can use the eval() function:
Example:
for i = 1:3
eval(['val' num2str(i) '=' num2str(i * 10)]);
end
The output is:
val1 =
10
val2 =
20
val3 =
30
Another way, using a struct to save the loop index into the name of the field:
for ii=1:bar
foo.(["var" num2str(ii)]) = quux;
end
This creates a structure with fields like foo.var1, foo.var1 etc. This does what you want without using eval.

Matlab: dynamic name for structure

I want to create a structure with a variable name in a matlab script. The idea is to extract a part of an input string filled by the user and to create a structure with this name. For example:
CompleteCaseName = input('s');
USER WRITES '2013-06-12_test001_blabla';
CompleteCaseName = '2013-06-12_test001_blabla'
casename(12:18) = struct('x','y','z');
In this example, casename(12:18) gives me the result test001.
I would like to do this to allow me to compare easily two cases by importing the results of each case successively. So I could write, for instance :
plot(test001.x,test001.y,test002.x,test002.y);
The problem is that the line casename(12:18) = struct('x','y','z'); is invalid for Matlab because it makes me change a string to a struct. All the examples I find with struct are based on a definition like
S = struct('x','y','z');
And I can't find a way to make a dynamical name for S based on a string.
I hope someone understood what I write :) I checked on the FAQ and with Google but I wasn't able to find the same problem.
Use a structure with a dynamic field name.
For example,
mydata.(casename(12:18)) = struct;
will give you a struct mydata with a field test001.
You can then later add your x, y, z fields to this.
You can use the fields later either by mydata.test001.x, or by mydata.(casename(12:18)).x.
If at all possible, try to stay away from using eval, as another answer suggests. It makes things very difficult to debug, and the example given there, which directly evals user input:
eval('%s = struct(''x'',''y'',''z'');',casename(12:18));
is even a security risk - what happens if the user types in a string where the selected characters are system(''rm -r /''); a? Something bad, that's what.
As I already commented, the best case scenario is when all your x and y vectors have same length. In this case you can store all data from the different files into 2 matrices and call plot(x,y) to plot each column as a series.
Alternatively, you can use a cell array such that:
c = cell(2,nufiles);
for ii = 1:numfiles
c{1,ii} = import x data from file ii
c{2,ii} = import y data from file ii
end
plot(c{:})
A structure, on the other hand
s.('test001').x = ...
s.('test001').y = ...
Use eval:
eval(sprintf('%s = struct(''x'',''y'',''z'');',casename(12:18)));
Edit: apologies, forgot the sprintf.