This is my code program which is x is my data, and i have another data name such as af4,f7 and f8.. How can I do looping technique on my program, so that the x will be automatically change into af4, then f7 and last f8 in Matlab?
x=af3;
d = fdesign.lowpass('Fp,Fst,Ap,Ast',4,5,1,40,128);
Hd = design(d,'butter');
fvtool(Hd);
y_delta = filter(Hd,x);
How do you generate these variables af4, af7 and af8? If you can create them as cells in a cell array or as fields in struct - your life would be much easier.
If you have no control over the variables, you can use eval:
varNames = {'af3', 'af4', 'af7', 'af8' }; % as strings
for vi=1:numel(varNames)
x = eval( varNames{vi} ); % here''s the trick
% continue here with x...
end
Note however that it is extremely unrecomanded to use eval.
I think this is what you could use:
xCell = {af3, af4, af7, af8};
for xi = 1:nnumel(xCell)
x = xCell{xi};
% do what you want to do with x
end
Related
For debugging, i wish to compare several objects, and create some unique ID for each them, and according its contents and structure, the ID should be equal. Is there any existing function for doing this?
For example if an object is an structure:
S:
S.a1 = 1
S.a2 = 2
S.b1 = 3
S.b11 = 4
S.b12 = 5
S.c1 = 6
My current choice is copying it to the disk and calculate a MD5 64-bit checksum, which do not work because this hash depends on the modified date of the file.
One solution is mentioned here. DataHash function is that solution:
function H = DataHash(Data)
Engine = java.security.MessageDigest.getInstance('MD5');
H = CoreHash(Data, Engine);
H = sprintf('%.2x', H); % To hex string
function H = CoreHash(Data, Engine)
% Consider the type of empty arrays:
S = [class(Data), sprintf('%d ', size(Data))];
Engine.update(typecast(uint16(S(:)), 'uint8'));
H = double(typecast(Engine.digest, 'uint8'));
if isa(Data, 'struct')
n = numel(Data);
if n == 1 % Scalar struct:
F = sort(fieldnames(Data)); % ignore order of fields
for iField = 1:length(F)
H = bitxor(H, CoreHash(Data.(F{iField}), Engine));
end
else % Struct array:
for iS = 1:n
H = bitxor(H, CoreHash(Data(iS), Engine));
end
end
elseif isempty(Data)
% No further actions needed
elseif isnumeric(Data)
Engine.update(typecast(Data(:), 'uint8'));
H = bitxor(H, double(typecast(Engine.digest, 'uint8')));
elseif ischar(Data) % Silly TYPECAST cannot handle CHAR
Engine.update(typecast(uint16(Data(:)), 'uint8'));
H = bitxor(H, double(typecast(Engine.digest, 'uint8')));
elseif iscell(Data)
for iS = 1:numel(Data)
H = bitxor(H, CoreHash(Data{iS}, Engine));
end
elseif islogical(Data)
Engine.update(typecast(uint8(Data(:)), 'uint8'));
H = bitxor(H, double(typecast(Engine.digest, 'uint8')));
elseif isa(Data, 'function_handle')
H = bitxor(H, CoreHash(functions(Data), Engine));
else
warning(['Type of variable not considered: ', class(Data)]);
end
Also, you can find the complete version of the code here.
A more general solution than #OmG 's answer, that relies on a little bit of undocumented functionality:
function str = hash(in)
% Get a bytestream from the input. Note that this calls saveobj.
inbs = getByteStreamFromArray(in);
% Create hash using Java Security Message Digest.
md = java.security.MessageDigest.getInstance('SHA1');
md.update(inbs);
% Convert to uint8.
d = typecast(md.digest, 'uint8');
% Convert to a hex string.
str = dec2hex(d)';
str = lower(str(:)');
The undocumented function getByteStreamFromArray returns the byte stream that would be written to disk if you were to call the save -v7 command on the variable. It works for any variable that is less than 2GB in size, including not only the built-in types (numeric, logical, struct, cell etc.) covered by #OmG 's CoreHash, but also built-in and user-defined classes as well.
Note that getByteStreamFromArray calls saveobj, so it will ignore Transient properties - this is almost certainly a good thing for hashing as well as saving.
PS In either solution, SHA1 is probably better than MD5.
Hi for my code I would like to know how to best save my variable column. column is 733x1. Ideally I would like to have
column1(y)=column, but I obtain the error:
Conversion to cell from logical is not possible.
in the inner loop. I find it difficult to access these stored values in overlap.
for i = 1:7
for y = 1:ydim % ydim = 436
%execute code %code produces different 'column' on each iteration
column1{y} = column; %'column' size 733x1 %altogether 436 sets of 'column'
end
overlap{i} = column1; %iterates 7 times.
end
Ideally I want overlap to store 7 variables saved that are (733x436).
Thanks.
I'm assuming column is calculated using a procedure where each column is dependent on the latter. If not, then there are very likely improvements that can be made to this:
column = zeros(733, 1); % Might not need this. Depends on you code.
all_columns = zeros(xdim, ydim); % Pre-allocate memory (always do this)
% Note that the first dimension is usually called x,
% and the second called y in MATLAB
overlap = cell(7, 1);
overlap(:) = {zeros(xdim, ydim)}; % Pre-allocate memory
for ii = 1:numel(overlap) % numel is better than length
for jj = 1:ydim % ii and jj are better than i and j
% several_lines_of_code_to_calculate_column
column = something;
all_columns(:, jj) = column;
end
overlap{ii} = all_columns;
end
You can access the variables in overlap like this: overlap{1}(1,1);. This will get the first element in the first cell. overlap{2} will get the entire matrix in the second cell.
You specified that you wanted 7 variables. Your code implies that you know that cells are better than assigning it to different variables (var1, var2 ...). Good! The solution with different variables is bad bad bad.
Instead of using a cell array, you could instead use a 3D-array. This might make processing later on faster, if you can vectorize stuff for instance.
This will be:
column = zeros(733, 1); % Might not need this. Depends on you code.
overlap = zeros(xdim, ydim, 7) % Pre-allocate memory for 3D-matrix
for ii = 1:7
for jj = 1:ydim
% several_lines_of_code_to_calculate_column
column = something;
all_column(:, jj, ii) = column;
end
end
I would like to name variable (type double) in the following way:
k0 = D(1,1);
k1 = D(2,2);
k2 = D(3,3);
k3 = D(4,4);
k4 = D(5,5);
k5 = D(6,6);
k6 = D(7,7);
k7 = D(8,8);
...
up to k99 automatically using for loop. So I see that I should use array or cell instead of double variable using eval as it is slow. But if I should use array or cell instead of double variable, I have to start at k{1} or k(1), which loses the meaning as I want exactly that k0 refers to D(1,1), i.e. the number in my variable is 1 less. How do I create meaningful cell name like k{0}?
Also, say I have an array A. There are also some times i need meaningful variable name, such as
c111 = A(1)*A(1)*A(1)
c222 = A(2)*A(2)*A(2)
c333 = A(3)*A(3)*A(3)
How can I create c{111} efficiently using for loop?
Use structures:
D = rand(21);
c = 1;
for k = -10:10
if k<0
s.(['k_' num2str(abs(k))]) = D(c,c);
else
s.(['k' num2str(k)]) = D(c,c);
end
c = c+1;
end
This will give you a structure like:
s =
k_10: 0.51785
k_9: 0.90121
k_8: 0.40746
k_7: 0.092989
.
.
k_1: 0.75522
k0: 0.55257
k1: 0.28708
.
.
k9: 0.94182
k10: 0.2124
and don't use eval...
Answer to 1st Question:-
D=randn(100); % A matrix of random elements of size 8x8
for m=0:99
assignin('base', ['k' num2str(m)], D(m+1,m+1))
end
Answer to 2nd Question:-
A=randn(1,3); % An array of 3 random elements
for n=1:3
assignin('base', ['c' num2str(111*n)], A(n)^3)
end
Comments:-
You've stated that you need variables like k0,k1,k2,... and c111,c222,c333 but you're asking how to create k{0}, k{1},k{2},... and c{111},c{222},c{333}. As far as your need is concerned, I have given answer to it. Regarding the latter, k{0} is never possible and c{111},c{222},c{333},... don't make good sense without using any of the first 0:100 values and then 112:221 values and so on. Although you can do it using:
A=rand(1,3); % An array of 3 random elements
c{333} = 0 ; % Pre-allocation
for p=1:3 % Since you want to use a 'for loop'
c{111*p} = A(p)^3;
end
And regarding the requirement that you made in the comment in these words "I also have some variable using negative index", you can never have variables in the negative index. If you mean you want to create variables with names like k-1, k-2,... etc, it is not possible. An alternate way is to use k_1, k_2,... etc but then as you said in the question "k0 refers to D(1,1), i.e. the number in my variable is 1 less". It means k_1 will refer to D(0,0) and so on which is again an invalid thing for MATLAB.
Recommendation:-
You really need to modify your code.
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.
I'm trying to have a hist function in a for loop because I work with varying amounts of datasets each time and its much faster and easier that having to edit a script each time, but I can't get it right. Can I have some help please? In essence I'm trying to have this in a for loop for variable number of unc{i} datasets and i number of [h{i},x{i}] resulting arrays:
[h1,x1] = hist(unc1,range);
[h2,x2] = hist(unc2,range);
[h3,x3] = hist(unc3,range);
[h4,x4] = hist(unc4,range);
Any help would be greatly appreciated. Thanking you in advance
Desclaimer: the use of eval is dangerous!
Let's say you have n uncs arrays. You can use struct to store them
for ii=1:n
cmd = sprintf( 's.unc%d = unc%d;', ii, ii );
eval( cmd );
end
Once you have the uncs is a sttruct, you can simply
for ii=n:-1:1
[h{ii} x{ii}] = hist( s.(sprintf('unc%d',ii)), range );
end
Notes:
1. Note that I used a backward loop for computing the histograms: this is a nice trick to preallocate h and x, see this thread.
2. It is extremly unwise to use eval, therefore, it might be wiser to create the different uncs arrays as a struct fields to begin with, skipping the first part of this answer.
You can put each of your input datasets in a cell array, and the output of the histograms in a second cell array.
For example,
unc1 = rand(5,1);
unc2 = rand(5,1);
unc3 = rand(5,1);
unc_cell = {unc1, unc2, unc3};
h_cell = cell(3, 1);
x_cell = cell(3, 1);
for ii = 1:3
[h{ii} x{ii}] = hist(unc_cell{ii});
end
This does require preloading all of the datasets and holding them in memory simultaneously. If this would use too much memory, you can load the datasets in the for loop rather than preloading them.
For example,
h_cell = cell(3, 1);
x_cell = cell(3, 1);
for ii = 1:3
unc = load(sprintf('data_%d.mat', ii)); %You would replace this with your file name
[h{ii} x{ii}] = hist(unc);
end