matlab for loop hang - matlab

i am doing a simulation and code for a for loops
for example
IntervalInterArrivalTime = [2 3 4 5] //user input
CDF = [250 500 750 1000] // this is the probability but multiply 1000 to alculate the range
randInterArrival = [991 351 754 823] // this is pc random generated number so each time wwill be different
lengthCDF = length(CDF); // length of the CDF which in this case is =4
period = 0;
the for loop i want do is the program will check the range of the randInterArrival with the CDF and IntervalArrivalTime. For example:
if randInterArrival >0 and <= CDF(1) , then period will be IntervalInterArrivalTime(1)
else if randInterArrival > CDF(1) and <= CDF(2) , then the period will be IntervalInterArrival(2)
else if randInterArrival > CDF(2) and <= CDF(3) , then the period will be IntervalInterArrival(3)
else if randInterArrival > CDF(3) and <= CDF(4) , then the period will be IntervalInterArrival(4)
for i=1:lengthCDF
if randInterArrival(i)>0 && randInterArrival(i)< CDF(i)
period=IntervalInterArrivalTime(i)
else if randInterArrival(i)> CDF(i) % how to continued to write the statement out so that i can loop through all the items in the CDF and check which IntervalInterArrival() it is
% i stop here and dunno how to continued to loop through the CDF and check
end
end
hope u all can help . thanks in advance

You could do this the way you're proposing, by checking each condition separately. However, this gets obnoxiously clunky as you increase the number of elements/conditions to check. A better way is to make use of the find function and rethink the logic of what you're trying to do:
What is the goal? The goal is to determine the index of the smallest CDF value that is larger than randInterArrival(i). Do this as follows:
index = find(CDF > randInterArrival(i), 1, 'first');
Voila! No if statements necessary. Use this index to get the period:
period = IntervalInterArrivalTime(index);

You need to end your statements:
for i=1:lengthCDF
if randInterArrival(i)>0 && randInterArrival(i)< CDF(i)
period=IntervalInterArrivalTime(i)
else if randInterArrival(i)> CDF(i) && ?? // i hang here ..
end
end

Related

How to increase time by 1s and replace old DT_i with the new one

I'm trying to calculate the DT value from a model I set up on Sim4Life. Firstly, i'd like to say that I am a complete beginner and I am trying to understand how programming works in general.
Now, I have a function with some constants and two variables, the one being time Dt (starting from 1 sec to 900 secs) and the other being the initial DT_i value. I want to calculate the increase of temperature for every second and create a loop that replaces the DT_i value with the DT_1_i value and also calculates the increased temperature DT_i_1. The function looks like this: DT_1_i=DT_i+Dt.
I know it is a very simple problem but I couldn't work my way through other similar questions. Any help would be appreciated.
Temperature variation:
You need initial temperature variation , I used 0
T(i+1) stands for Next temperature variation
T(i) stands for present temperature variation
i stands for time step, dt
Read through comment in my code
Time
Use for loop to set the time for i = 1 : 900 %Temperature increase end
i =1:900 just means
first run use time = 1s,
second run time = 1+1 = 2
so on till 900
The code is as follow
% Initial Temperature variation is set to zero, unless you have some data
d = 1.3;
c = 3.7;
S_i = 3*10^3;
t_reg = 900;
%Time
t = 1:900;
% Length oftime to help me know the size of the variable needed to
% initialize
l = length(t);
% Initialize variable that used to store DT it helps speed up
% comutation
% Initial Temperature variation is set to zero, unless you have some data
DT = zeros(1, l);
for i = 1:900
% the value of i represent dt, first run i = 1, dt = 1, second run
% i = 2 and dt = 2 so on
if i == 900
%do nothing already reached the last index 900, i+1 = 901 will be
%out of range
else
DT(i+1) = DT(i) + (i./t_reg).*(d.*sqrt(c*S_i)-DT(i+1));
end
end

Matlab simple matrix manip

I'm new to Matlab and I want to achieve a very simple operation : I have a 792 x 1046 uint8 matrix called mg and want to convert its cells values (from 0 to 255) to values between 1 and 4 (1,2,3,4) in a new matrix called mgc accordingly to simple conditions.
Strangely, the new matrix is filled with only 1s and 2s but not any 3s or 4s...
Here is my code :
[x,y]=size(mg);
mgc = zeros(x,y);
for i=1:x
for j=1:y
if (mg(i,j)<=100)
mgc(i,j)=1;
elseif (100<mg(i,j)<=110)
mgc(i,j)=2;
elseif (110<mg(i,j)<=120)
mgc(i,j)=3;
else
mgc(i,j)=4;
end
end
end
If anyone could help me solve this stupid issue, it would be great !
THX
You shouldn't use expressions such as 100<mg(i,j)<=110 in MATLAB. Instead, use something like 100<mg(i,j) && mg(i,j)<=110.
At the moment, MATLAB is evaluating the expression 100<mg(i,j)<=110 as (100<mg(i,j))<=110. (100<mg(i,j)) is going to be either one or zero (true or false), and therefore will always be <=110. So it never gets past the second else, and your array is all either 1 or 2.
Edit: although this answer explains the specific issue you're having, you should probably instead be using logical indexing, which would be much more efficient than a double for loop (and more idiomatic in MATLAB). See the answers from #excaza or #Benoit_11 for examples of that).
As stated in the comments you need to use logical operators in your elseif statements. Just so you know, you can vectorize this whole for loop with those same logical operators as follows:
Let's define mgc2 as you did for mgc:
mgc2 = zeros(x,y);
Then you can fill mgc2 like this:
mgc2(mg<=100) =1;
mgc2(mg>100 & mg<=110) =2;
mgc2(mg>110 & mg <=120) =3;
mgc2(mg>120) =4;
You need to use and operators:
% Dummy data
mg = [10 115; 125 140];
[x,y]=size(mg);
mgc = zeros(x,y);
for i=1:x
for j=1:y
if (mg(i,j)<=100)
mgc(i,j)=1;
elseif (100 < mg(i,j) && mg(i,j) <= 110)
mgc(i,j)=2;
elseif (110 < mg(i,j) && mg(i,j) <= 120)
mgc(i,j)=3;
else
mgc(i,j)=4;
end
end
end
Returns:
mgc =
1 3
4 4
You also don't need to use a loop here, and can leverage MATLAB's logical indexing instead:
% Dummy data
mg = [10 115; 125 140];
mgc = zeros(size(mg));
mgc(mg <= 100) = 1;
mgc((mg > 100 & mg <= 110)) = 2;
mgc((mg > 110 & mg <= 120)) = 3;
mgc(mg > 120) = 4;
Which returns the same matrix.
This is because any value greater than 100 will return true for the first elseif statement.
100 < my(i,j) returns 1.
When you want to do a double condition, you must use the & operator otherwise you may have false statements
>> x = 4
>> res = 2<x<=3
res =
1
%%Using the `&` operator instead
>> res = 2<x && x<=3
res =
0

Problems with Plotting Matlab Function

I am Beginner in Matlab, i would like to plot system concentration vs time plot at a certain time interval following is the code that i have written
%Input function of 9 samples with activity and time calibrated with Well
%counter value approx : 1.856 from all 9 input values of 3 patients
function c_o = Sample_function(td,t_max,A,B)
t =(0 : 100 :5000); % time of the sample post injection in mins
c =(0 : 2275.3 :113765);
A_max= max(c); %Max value of Concentration (Peak of the curve)
if (t >=0 && t <= td)
c_o(t)=0;
else if(td <=t && t<=t_max)
c_o(t)= A_max*(t-td);
else if(t >= t_max)
c_o(t)=(A(1)*exp(-B(1)*(t-t_max)))+(A(2)*exp(-B(2)*(t- t_max)))+...
(A(3)*exp(-B(3)*(t-t_max)));
end
fprintf('plotting Data ...\n');
hold on;
figure;
plot(c_o);
xlabel('Activity of the sample Ba/ml ');
ylabel('time of the sample in minutes');
title (' Input function: Activity sample VS time ');
pause;
end
I am getting following error
Operands to the || and && operators must be convertible to logical scalar values.
Error in Sample_function (line 18)
if (t >=0 && t <= td)
Kindly .Let me know if my logic is incorrect
Your t is not a single value to compare with 0 so it cannot evaluate to true or false.
You want to do this with logical indexing
c_o = zeros(size(t));
c_o(t>=0 & t<=td) = 0; % this line is actually redundant and unnecessary since we initialized the vector to zeros
c_o(t>td & t<=t_max) = A_max*(t(t>td & t<=t_max)-td);
c_o(t>t_max) = (A(1)*exp(-B(1)*(t(t>t_max)-t_max)))+(A(2)*exp(-B(2)*(t(t>t_max)- t_max)))...
+ (A(3)*exp(-B(3)*(t(t>t_max)-t_max)));
You could also make this a little prettier (and easier to read) by assigning the logical indexes to variables:
reg1 = (t>=0 & t<=td);
reg2 = (t>td & t<=t_max);
reg3 = (t>t_max);
Then, for instance, the second assignment becomes the much more readable:
c_o(reg2) = A_max*(t(reg2)-td);
t is written as a array of numbers. So, it can't be compared with a scalar value ex. 0.
Try it in a for loop
for i=1:length(t)
if (t(i) >=0 && t(i) <= td)
c_o(t(i))=0;
else if(td <=t(i) && t(i)<=t_max)
c_o(t(i)))= A_max*(t(i)-td);
else if(t(i) >= t_max)
c_o(t)=(A(1)*exp(-B(1)*(t(i)-t_max)))+(A(2)*exp(-B(2)*(t(i)- t_max)))...
+ (A(3)*exp(-B(3)*(t(i)-t_max)));
end
end

find consecutive nonzero values

I am trying to write a simple MATLAB program that will find the first chain (more than 70) of consecutive nonzero values and return the starting value of that consecutive chain.
I am working with movement data from a joystick and there are a few thousand rows of data with a mix of zeros and nonzero values before the actual trial begins (coming from subjects slightly moving the joystick before the trial actually started).
I need to get rid of these rows before I can start analyzing the movement from the trials.
I am sure this is a relatively simple thing to do so I was hoping someone could offer insight.
Thank you in advance
EDIT: Here's what I tried:
s = zeros(size(x1));
for i=2:length(x1)
if(x1(i-1) ~= 0)
s(i) = 1 + s(i-1);
end
end
display(S);
for a vector x1 which has a max chain of 72 but I dont know how to find the max chain and return its first value, so I know where to trim. I also really don't think this is the best strategy, since the max chain in my data will be tens of thousands of values.
This answer is generic for any chain size. It finds the longest chain in a vector x1 and retrieves the first element of that chain val.
First we'll use bwlabel to label connected components, For example:
s=bwlabel(x1);
Then we can use tabulate to get a frequency table of s, and find the first element of the biggest connected component:
t=tabulate(s);
[C,I]=max(t(:,2));
val=x1(find(s==t(I,1),1, 'first'));
This should work for the case you have one distinct maximal size chain. What happens for the case if you have more than one chain that has maximal lengths? (you can still use my code with slight modifications...)
You don't need to use an auxiliary vector to keep track of the index:
for i = 1:length(x)
if x(i) ~= 0
count = count + 1;
elseif count >= 70
lastIndex = i;
break;
else
count = 0;
end
if count == 70
index = i - 69;
end
end
To remove all of the elements in the chain from x, you can simply do:
x = x([lastIndex + 1:end]);
EDIT (based off comment):
The reason that the way you did it didn't work was because you didn't reset the counter when you ran into a 0, that's what the:
else
count = 0;
is for; it resets the process, if you will.
For some more clarity, in your original code, this would be reflected by:
if x1(i-1) ~= 0
s(i) = 1 + s(i-1);
else
s(i) = 0;
end

Cutting down large matrix iteration time

I have some massive matrix computation to do in MATLAB. It's nothing complicated (see below). I'm having issues with making computation in MATLAB efficient. What I have below works but the time it takes simply isn't feasible because of the computation time.
for i = 1 : 100
for j = 1 : 20000
element = matrix{i}(j,1);
if element <= bigNum && element >= smallNum
count = count + 1;
end
end
end
Is there a way of making this faster? MATLAB is meant to be good at these problems so I would imagine so?
Thank you :).
count = 0
for i = 1:100
count = count + sum(matrix{i}(:,1) <= bigNum & matrix{i}(:,1) >= smallNum);
end
If your matrix is a matrix, then this will do:
count = sum(matrix(:) >= smallNum & matrix(:) <= bigNum);
If your matrix is really huge, use anyExceed. You can profile (check the running time) of both functions on matrix and decide.