Use of Logical Masks - matlab

I working on a homework assignment and trying to solve the following problem:
Here is the code I have so far:
function [ ] = Activity45( Time )
%Homework 4
%Activity 4.5
t=Time;
A=[0:0.1:t];
B=3*exp(-(A/3)).*sin(pi.*A);
C=(B>0);
plot(A,B(C))
end
So I am trying to use a mask to extract the data from Matrix B in Matrix C. But I do not know how to match the data up between A and C, to then use plot().
Any help?

With plot(A(C), B(C)) you don't get the intended curve because you don't have values equal to zero. Instead the last two points to the left and right are connected with a line above 0. The right way would be to set the value on the Y-Axis to zero.
B(~C)=0;
plot(A,B);
For future formulas, it might be a good idea to use variable names matching the variable names in your formulas.

Related

MATLAB struct conversion error

I have 5 different structure and I want to calculate some variables for all of them. To do that, I wrote the following code:
for i=1:5
[StructureI(i), ReqTab(i), jt(i), B(i)]=Checkall(E);
end
The values StructureI, ReqTab, jt and B are calculated in another function and they are
StructureI= 1X4 matrix,
ReqTab= 4X2 matrix,
jt=2x1 matrix,
B=4x4 matrix
When I run the code it calculates all the varibles in the function Checkall. However, when it turns to the parent code, it gives and error "Conversion to double from struct is not possible."
How can I solve this problem?
Thanks in advance.
You cannot assign directly from double to struct, instead you have to write the specific field field_name to assign to:
[StructureI(i).field_name, ReqTab(i), jt(i), B(i)] = Checkall(E);
If all of these variables (i.e. also ReqTab, jt, B) are structures, then off course you need to specify the field in each one of them, using the . notation.
However, as mentioned in the comments, all iterations of your loop are just the same (no usage of i within it), so why do you need this loop? just to make 5 copies?

Creating functions in Matlab

Hi, I am trying to write a function as per the question. I have tried to create four sub-matrices which are the reverse of each other and then multiply to give the products demanded by the question. My attempt:
function T = custom_blocksT(n,m)
T(1:end,end-1:1);
T(1:end,end:-1:1)*2;
T(1:end,end:-1:1)*3;
T(1:end,end:-1:1)*4;
What I'm unsure of is
(i) What do the the indivual sub-matrices(T(1:end,end-1:1);)need to be equal to? I was thinking of(1:3)?
(ii) I tried to create a generic sub-matrix which can take any size matrix input using end was this correct or can't you do that? I keep getting this error
Undefined function or variable 'T'.
Error in custom_blocksT (line 2)
T(1:end,end-1:1);
I have searched the Matlab documentation and stacked overflow, but the problem is I'm not quite sure what I'm supposed to be looking for in terms of solving this question.
If someone could help me I would be very thankfull.
There are many problems with your function:
function T = custom_blocksT(n,m)
T(1:end,end-1:1);
T(1:end,end:-1:1)*2;
T(1:end,end:-1:1)*3;
T(1:end,end:-1:1)*4;
end
This is an extremely basic question, I highly recommend you find and work through some very basic MATLAB tutorials before continuing, even before reading this answer to be honest.
That said here is what you should have done and a bit of what you did wrong:
First, you are getting the error that T dos not exist because it doesn't. The only variables that exist in your function are those that you create in the function or those that are passed in as parameters. You should have passed in T as a parameter, but instead you passed in n and m which you don't use.
In the question, they call the function using the example:
custom_blocks([1:3;3:-1:1])
So you can see that they are only passing in one variable, your function takes two and that's already a problem. The one variable is the matrix, not it's dimensions. And the matrix they are passing in is [1:3;3:-1:1] which if you type in the command line you will see gives you
[1 2 3
3 2 1]
So for your first line to take in one argument which is that matrix it should rather read
function TOut = custom_blocks(TIn)
Now what they are asking you to do is create a matrix, TOut, which is just different multiples of TIn concatenated.
What you've done with say TIn(1:end,end-1:1)*2; is just ask MATLAB to multiple TIn by 2 (that's the only correct bit) but then do nothing with it. Furthermore, indexing the rows by 1:end will do what you want (i.e. request all the rows) but in MATLAB you can actually just use : for that. Indexing the columns by end-1:1 will also call all the columns, but in reverse order. So in effect you are flipping your matrix left-to-right which I'm sure is not what you wanted. So you could have just written TIn(:,:) but since that's just requesting the entire matrix unchanged you could actually just write TIn.
So now to multiply and concatenate (i.e. stick together) you do this
TOut = [TIn, TIn*2; TIn*3, TIn*4]
The [] is like a concatenate operation where , is for horizontal and ; is for vertical concatenation.
Putting it all together:
function TOut = custom_blocks(TIn)
TOut = [TIn, TIn*2; TIn*3, TIn*4];
end

Subscripted assignment dimension mismatch

here is the code listing and i got the above mentiond error at line nests(r,c)=nests(r,c)+stepsize.*randn(size(nests(r,c))); please let me now what is wrong with my code as i m new to matlab
for r = 1:numb_of_nest % for each particle
for c = 1:4
u=randn(size(nests(r,c)))*sigma;
v=randn(size(nests(r,c)));
step=u./abs(v).^(1/beta);
nests(r,c)=nests(r,c)+stepsize.*randn(size(nests(r,c)));
% Apply simple bounds/limits
ns_tmp=nests(r,c);
I=ns_tmp<Lb(c);
ns_tmp(I)=Lb(I);
% Apply the upper bounds
J=ns_tmp>Ub(c);
ns_tmp(J)=Ub(J);
% Update this new move
nests(r,c)=ns_tmp;
end
end
This error happens when you assign a value of some dimension m x n to a subscripted variable of different dimension.
In your case, assuming nests has no third dimension, you're assigning to a scalar (1x1) variable. This only works if the value you're trying to assign also is a scalar. Since you get the error, it probably isn't. The only place where your dimensions can be non-scalar is stepsize, so to fix this error, make sure stepsize is a scalar value.
According to the definition you gave in an earlier comment (stepsize=0.01*step.*(nests(r,c)-best);), this problem translates to make sure best is a scalar value. Possibly by subscripting, I can't tell you exactly how since I don't know what best is.
step=u./abs(v).^(1/beta);
nests(r,c)=nests(r,c)+stepsize.*randn(size(nests(r,c)));
Here you're assigning a value to the variable step, but then using a different variable called stepsize that hasn't been assigned a value anywhere in this code. Is this intentional? If not, stepsize is probably some leftover variable from previous code which is messing up the dimensions and giving you this error.
In addition to the above, is nests an ordinary two-dimensional matrix in your code? If so, taking size(nests(r,c)) every time is unnecessary - since you're giving two subscripts, the result is only going to be 1 all the time. Or is nests a cell array perhaps? In that case, you might want to index using curly braces { } instead of ordinary parantheses, to get the size of the matrix that's sitting inside the cell.

Diffusion outer bounds

I'm attempting to run this simple diffusion case (I understand that it isn't ideal generally), and I'm doing fine with getting the inside of the solid, but need some help with the outer edges.
global M
size=100
M=zeros(size,size);
M(25,25)=50;
for diffusive_steps=1:500
oldM=M;
newM=zeros(size,size);
for i=2:size-1;
for j=2:size-1;
%we're considering the ij-th pixel
pixel_conc=oldM(i,j);
newM(i,j+1)=newM(i,j+1)+pixel_conc/4;
newM(i,j-1)=newM(i,j-1)+pixel_conc/4;
newM(i+1,j)=newM(i+1,j)+pixel_conc/4;
newM(i-1,j)=newM(i-1,j)+pixel_conc/4;
end
end
M=newM;
end
It's a pretty simple piece of code, and I know that. I'm not very good at using Octave yet (chemist by trade), so I'd appreciate any help!
If you have concerns about the border of your simulation you could pad your matrix with NaN values, and then remove the border after the simulation has completed. NaN stands for not a number and is often used to denote blank data. There are many MATLAB functions work in a useful way with these values.
e.g. finding the mean of an array which has blanks:
nanmean([0 nan 5 nan 10])
ans =
5
In your case, I would start by adding a border of NaNs to your M matrix. I'm using 'n' instead of 'size', since size is an important function in MATLAB, and using it as a variable can lead to confusing errors.
n=100;
blankM=zeros(n+2,n+2);
blankM([1,end],:) = nan;
blankM(:, [1,end]) = nan;
Now we can define 'M'. N.B that the first column and row will be NaNs so we need to add an offset (25+1):
M = blankM;
M(26,26)=50;
Run the simulation through,
m = size(blankM, 1);
n = size(blankM, 2);
for diffusive_steps=1:500
oldM = M;
newM = blankM;
for i=2:m-1;
for j=2:n-1;
pixel_conc=oldM(i,j);
newM(i,j+1)=newM(i,j+1)+pixel_conc/4;
newM(i,j-1)=newM(i,j-1)+pixel_conc/4;
newM(i+1,j)=newM(i+1,j)+pixel_conc/4;
newM(i-1,j)=newM(i-1,j)+pixel_conc/4;
end
end
M=newM;
end
and then extract the area of interest
finalResult = M(2:end-1, 2:end-1);
One simple change you might make is to add a boundary of ghost cells, or halo, around the domain of interest. Rather than mis-use the name size I've used a variable called sz. Replace:
M=zeros(sz,sz)
with
M=zeros(sz+2,sz+2)
and then compute your diffusion over the interior of this augmented matrix, ie over cells (2:sz+1,2:sz+1). When it comes to considering the results, discard or just ignore the halo.
Even simpler would be to simply take what you already have and ignore the cells in your existing matrix which are on the N,S,E,W edges.
This technique is widely used in problems such as, and similar to, yours and avoids the need to write code which deals with the computations on cells which don't have a full complement of neighbours. Setting the appropriate value for the contents of the halo cells is a problem-dependent matter, 0 isn't always the right value.

plotting from a loop in matlab

I get some strange problem in my matlab code, this is a part of my code:
for k=1:length(box11)
num_pts1(k)=sum(length(find(box11(:,k)>0)));
size1=sum(length(find(box11(:,:)>0)));
perc1(k)=(num_pts1(k)/size1)*100;
end
plot(delta,perc1(k),'*')
However, the problem is that I get perc1 fixed in my plot. so I see a straight line in the graph. but I would like to have different numbers which give a curve line to me..
plzzzzzzzzzzzzzzzz, any help :( !!!
You should recall that length returns the length of an array. So, in the instruction
num_pts1(k)=sum(length(find(box11(:,k)>0)));
the operator sum acts on a scalar (which equals the length of the array find(box11(:,k)>0)), and not on an array. The same holds true for the instruction
size1=sum(length(find(box11(:,:)>0)));
So, if the length of find(box11(:,k)>0) does not change with k, then your perc1 will keep constant.