How to access and modify values of variables in matlab workspace? - matlab

There are few variables in my matlab workspace, lets say a and b.
eg: a = 1:5;
b = 1:10;
I used who to get their names.
like listVariables = who;
now listVariables has the variable names a and b, but i dont know how to access their values so that I can do some mathematical operations on them.

It looks like evalin is what your are searching for:
a_val = evalin('base', listVariables{1});
b_val = evalin('base', listVariables{2});
The advantage of evalin is that it can be executed from a function (out of the scope of the workspace).
Example:
In workspace:
a = 1:5; b = 1:10;
Content of my_fun.m:
function my_fun()
listVariables = evalin('base', 'who');
a_val = evalin('base', listVariables{1});
b_val = evalin('base', listVariables{2});
display(a_val);
display(b_val);
Result of my_fun() execution:
a_val =
1 2 3 4 5
b_val =
1 2 3 4 5 6 7 8 9 10
Note: there are cases in which evalin is useful, but it's not a good coding practice.

Related

Return property directly when class is called (Matlab)

I have a class called foo with only property M,
classdef foo
properties
M
end
methods
function obj = foo(arg1)
M=arg1;
end
end
end
and I create the object:
F=foo(1)
In C++ it is possible, that when I call F, that I directly get the value of one chosen variable. In my case I would like to get F.M when I just write F. For example this would allow to write
size(F)
instead of writing
size(F.M)
or defining a method size for my class. Is there a way in MATLAB to achieve this?
Edit: In other words, whenever I write F, I want that MATLAB reads it as F.M.
Edit: I will clarify what I want to acchieve.
My class represents a matrix whose values are multivariate infinite sequences with compact support. Thus I have to do a lot of bookkeeping not to mix up all the indices. Things I want to do with my matrix:
Matrix multiplication.
Convolution.
Upsampling, downsampling.
Everything else which is possible in a vector/matrix space.
I thought this is easier to acchieve when I encapsulate all the meta-data (this are the indices of the 0^th entries of the sequence) together with the data.
Because my class is actually a matrix, most operations work on that class in the same way as on ordinary matrices. Therefore I do not want to code it all over again (Because of code-maintenance, less bugs, code-readability).
In C++ I could do it that way. It seems, my approach to that problem is the wrong one in MATLAB.
You have to overload the function size as I mentioned in my comment.
classdef foo
properties
M
end
methods
function obj = foo(arg)
obj.M = arg;
end
function varargout = size(obj, varargin)
if nargin == 1
varargout = size(obj.M);
elseif nargin == 2 && nargout == 1
varargout = size(obj.M, varargin{1})
else
error('Wrong number of input or output arguments.')
end
end
function ret = mtimes(varargin)
try
ret = varargin{1}.M * varargin{2};
catch
ret = varargin{1} * varargin{2}.M;
end
end
end
end
Console Output:
>> F=foo(0:3);
>> size(F)
ans =
1 4
>> size(F, 2)
ans =
4
>> F*(4:7).'
ans =
38
>> (4:7).'*F
ans =
0 4 8 12
0 5 10 15
0 6 12 18
0 7 14 21
I could continue but preparing the console output for StackOverflow is horrible...

Memory-Allocation for function calls of form x = f(x) in MATLAB

In my code, I have lots of places where I invoke functions of the form
X = f(X)
and X can be a rather large matrix. In my special case, I have mostly calls like
X = feval(somefunc, X)
or
X = obj.myfunc(X)
It would be bad if, every time the function is called, there is new space allocated for X. Is MATLAB smart enough to deal with such function calls? Is there a way to tell?
The answer to this question helps would help very much with a design descision. I like to program in object oriented style and if MATLAB is not smart enough for this, it might pay off for me to add another member for X in the class, although I would rather not do this otherwise.
Whether a copy is made of the input arguments or not when calling a function in MATLAB depends upon what happens inside of the function.
MATLAB uses a system referred to as copy-on-write. This means that if you pass a large variable to a function as an input, as long as you do not modify the variable within that function, the variable will not be copied into the workspace of the function and the function will instead read the data from it's current location in memory.
function Y = func(X)
Y = X + 1;
end
If you are modifying the variable within the function, then a copy of the input variable is made and placed into the local workspace of the function.
function X = func(X)
X = X + 1;
end
There is more information on Loren's Mathworks blog.
An easy way to determine if a copy of the data is made or not is to use the undocumented format debug mode which will show you where the data for a given variable is stored in memory.
format debug
%// Create a variable a and show where debug info
a = [1,2]
%// Structure address = 141f567f0
%// m = 1
%// n = 2
%// pr = 7f9540b85e20
%// pi = 0
%// 1 2
%// Assign b = a but don't modify
b = a
%// Structure address = 141f567f0
%// m = 1
%// n = 2
%// pr = 7f9540b85e20 <= POINTER TO DATA REMAINED UNCHANGED
%// pi = 0
%// 1 2
%// Modify (Will create a new copy)
b = b + 1
%// Structure address = 141f55b40
%// m = 1
%// n = 2
%// pr = 7f953bcf1a20 <= POINTER TO DATA CHANGED (COPY)
%// pi = 0
%// 2 3
If you prefer you can use this little anonymous function I've created to inspect the memory location of any particular variable.
memoryLocation = #(x)regexp(evalc('disp(x)'), '(?<=pr\s*=\s*)[a-z0-9]*', 'match')
a = [1,2];
memoryLocation(a)
%// 7f9540b85e20
b = a;
memoryLocation(b)
%// 7f9540b85e20
b = b + 1;
memoryLocation(b)
%// 7f953bcf1a20
As a bit of a side-note, I would recommend against using feval throughout your code and instead just use the function names directly.

MATLAB: Using a for loop within another function

I am trying to concatenate several structs. What I take from each struct depends on a function that requires a for loop. Here is my simplified array:
t = 1;
for t = 1:5 %this isn't the for loop I am asking about
a(t).data = t^2; %it just creates a simple struct with 5 data entries
end
Here I am doing concatenation manually:
A = [a(1:2).data a(1:3).data a(1:4).data a(1:5).data] %concatenation function
As you can see, the range (1:2), (1:3), (1:4), and (1:5) can be looped, which I attempt to do like this:
t = 2;
A = [for t = 2:5
a(1:t).data
end]
This results in an error "Illegal use of reserved keyword "for"."
How can I do a for loop within the concatenate function? Can I do loops within other functions in Matlab? Is there another way to do it, other than copy/pasting the line and changing 1 number manually?
You were close to getting it right! This will do what you want.
A = []; %% note: no need to initialize t, the for-loop takes care of that
for t = 2:5
A = [A a(1:t).data]
end
This seems strange though...you are concatenating the same elements over and over...in this example, you get the result:
A =
1 4 1 4 9 1 4 9 16 1 4 9 16 25
If what you really need is just the .data elements concatenated into a single array, then that is very simple:
A = [a.data]
A couple of notes about this: why are the brackets necessary? Because the expressions
a.data, a(1:t).data
don't return all the numbers in a single array, like many functions do. They return a separate answer for each element of the structure array. You can test this like so:
>> [b,c,d,e,f] = a.data
b =
1
c =
4
d =
9
e =
16
f =
25
Five different answers there. But MATLAB gives you a cheat -- the square brackets! Put an expression like a.data inside square brackets, and all of a sudden those separate answers are compressed into a single array. It's magic!
Another note: for very large arrays, the for-loop version here will be very slow. It would be better to allocate the memory for A ahead of time. In the for-loop here, MATLAB is dynamically resizing the array each time through, and that can be very slow if your for-loop has 1 million iterations. If it's less than 1000 or so, you won't notice it at all.
Finally, the reason that HBHB could not run your struct creating code at the top is that it doesn't work unless a is already defined in your workspace. If you initialize a like this:
%% t = 1; %% by the way, you don't need this, the t value is overwritten by the loop below
a = []; %% always initialize!
for t = 1:5 %this isn't the for loop I am asking about
a(t).data = t^2; %it just creates a simple struct with 5 data entries
end
then it runs for anyone the first time.
As an appendix to gariepy's answer:
The matrix concatenation
A = [A k];
as a way of appending to it is actually pretty slow. You end up reassigning N elements every time you concatenate to an N size vector. If all you're doing is adding elements to the end of it, it is better to use the following syntax
A(end+1) = k;
In MATLAB this is optimized such that on average you only need to reassign about 80% of the elements in a matrix. This might not seam much, but for 10k elements this adds up to ~ an order of magnitude of difference in time (at least for me).
Bare in mind that this works only in MATLAB 2012b and higher as described in this thead: Octave/Matlab: Adding new elements to a vector
This is the code I used. tic/toc syntax is not the most accurate method for profiling in MATLAB, but it illustrates the point.
close all; clear all; clc;
t_cnc = []; t_app = [];
N = 1000;
for n = 1:N;
% Concatenate
tic;
A = [];
for k = 1:n;
A = [A k];
end
t_cnc(end+1) = toc;
% Append
tic;
A = [];
for k = 1:n;
A(end+1) = k;
end
t_app(end+1) = toc;
end
t_cnc = t_cnc*1000; t_app = t_app*1000; % Convert to ms
% Fit a straight line on a log scale
P1 = polyfit(log(1:N),log(t_cnc),1); P_cnc = #(x) exp(P1(2)).*x.^P1(1);
P2 = polyfit(log(1:N),log(t_app),1); P_app = #(x) exp(P2(2)).*x.^P2(1);
% Plot and save
loglog(1:N,t_cnc,'.',1:N,P_cnc(1:N),'k--',...
1:N,t_app,'.',1:N,P_app(1:N),'k--');
grid on;
xlabel('log(N)');
ylabel('log(Elapsed time / ms)');
title('Concatenate vs. Append in MATLAB 2014b');
legend('A = [A k]',['O(N^{',num2str(P1(1)),'})'],...
'A(end+1) = k',['O(N^{',num2str(P2(1)),'})'],...
'Location','northwest');
saveas(gcf,'Cnc_vs_App_test.png');

Is there a 'self' to refer own struct in MATLAB?

I'm grouping a set of anonymous functions into a structure and some variables within that structure. Is there a way to refer 'self', i.e, own structure? What I'd like to accomplish is to have a function returns some values based on the member variables. For simplicity, say I have a struct a, where
a.value_1 = 3;
a.value_2 = 2;
a.sum = #()(self.value_1 + self.value_2)
Is there something like that possible in MATLAB?
Before objected-oriented programming was introduced in MATLAB (including both classdef-style and the obsolete #-directory style classes), one could create lightweight objects using closures and nested functions (lacking inheritance of course). This concept also exists in other languages.
Here is an example:
function s = mystruct()
s = struct('value_1',[], 'value_2',2, 'sum',#mysum);
s.value_1 = 3;
function out = mysum()
out = s.value_1 + s.value_2;
end
end
Which is used as:
>> s = mystruct()
s =
value_1: 3
value_2: 2
sum: #mystruct/mysum
>> s.value_1 = 10; % NOTE: this wont do what you expect!
>> s.sum()
ans =
5
Note that variables are immediately captured when creating a closure (functions have their own private copy if you will). So if you change one of the exposed fields from the returned structure, it will not be reflected in the enclosed state (think of them as read-only properties).
One solution is to provide accessor methods:
function obj = mystruct()
% think of those as private properties
value_1 = 3;
value_2 = 2;
% returned object (this or self)
obj = struct();
% public accessors for properties
obj.value_1 = #accessValue1;
function out = accessValue1(in)
if nargin > 0, value_1 = in; end
out = value_1;
end
obj.value_2 = #accessValue2;
function out = accessValue2(in)
if nargin > 0, value_2 = in; end
out = value_2;
end
% member method
obj.sum = #mysum;
function out = mysum()
out = value_1 + value_2;
end
end
So now we could say:
>> s = mystruct()
s =
value_1: #mystruct/accessValue1
value_2: #mystruct/accessValue1
sum: #mystruct/mysum
>> x = s.value_1(); % get
>> s.value_1(10); % set
>> s.sum()
ans =
12
Which is starting to look like the current recommended approach to create classes:
classdef mystruct < handle
properties
value_1 = 3;
value_2 = 2;
end
methods
function out = sum(obj)
out = obj.value_1 + obj.value_2;
end
end
end
Used in a similar manner:
>> s = mystruct()
s =
mystruct with properties:
value_1: 3
value_2: 2
>> s.value_1 = 10;
>> s.sum
ans =
12
We could also define get/set access methods as before..
This seems to work but I think you should rather create a class than a struct to do this:
a.value_1 = 3;
a.value_2 = 2;
a.sum = #(x)(x.value_1 + x.value_2)
a.sum(a)
With this change
a.value_1 = 3;
a.value_2 = 2;
a.sum = #()(a.value_1 + a.value_2)
Then a.sum() returns 5. But what happens when you change one of the values, later on, e.g., set a.value_1 = 5? Now a.sum() returns ... still 5. The parameters passed into the anonymous function are evaluated upon instantiation. If you want the second behavior to work properly you need to use a class. See my answer to this question for more. The only reason to use a function handle like you have is to avoid evaluating and storing a large output of a function until it's needed.

MATLAB: Copying Global variable for all Workers

I want to pass "a" as a global variable to the function "tsfn", say
function [ out ] = tsfn( )
global a;
out=a+1;
end
When I run the following I get the expected result:
>> global a;
a=1
out=[];
for i=1:4
out =[out tsfn()];
end
out
a =
1
out =
2 2 2 2
However if I run it with parfor instead of for I end up with a blank vector. Which leads me to believe that "a" is not being passed into the function. I'm wondering if there is a way to pass the variable as a global variable for all workers.
Thanks
Works fine on my platform. Try just restarting your computer or Matlab. Generally, the "parfor" loop accomplishes the same task as the "for" loop--each loop is computed in parallel. Declaring "global" in one or more functions and/or the base workspace allows each of them to access the contents of the global variable, so your usage is correct.
Here is my code:
function[ out ] = tsfn()
global a;
out = a + 1;
end
EDU>> global a;
EDU>> a = 1;
EDU>> out = [];
EDU>> parfor i = 1 : 4
out = [ out tsfn() ];
end
EDU>> a
a =
1
EDU>> out
out =
2 2 2 2
Aside, a simple way to test the contents of a variable inside a function is to remove the semicolon, which prints it to the editor.