How to assign range of integers in for loop using matlab and exclude a number in that range? - matlab

I would like to have a for loop with 1:25 range but I do not want the for loop to go through number 23 in that range
in another format; I want it like this 1:22 24:25
is it doable this way?
please help

Yes. You can write:
for num = [1:22 24:25]
% do something with num
end

Another solution:
for idx=1:25
if idx==23, continue, end
disp(num2str(idx));
end

Just to add an alternative:
skip = [23];
for idx = 1:25
if ~any(idx == skip)
%// Your code here
end
end
I think it's more readable than using [1:22 24:25] as your loop variable as you can see clearly and quickly which numbers are being skipped (unless [1:22 24:25] is a variable getting generated elsewhere in which case I would go with that method), it avoids continue which is controversial and it's easy to add other numbers to skip (i.e. skip = [7, 18, 23] etc...)

Related

Create an array that grows at a regular interval on Matlab

I have been thinking about how to create an array that grows at a regular interval of time (for instance every 5 seconds) on Matlab.
I figured out 2 ways, either using tic/ toc or timer function. Later this program will be complexified. I am not sure which way is the best but so far I am trying with using timer.
Here is what I have tried :
clc;
period=5;%period at which the file should be updated
freq=4;
l=freq*period;
time=[0];
a = timer('ExecutionMode','fixedRate','Period',period,'TimerFcn',{#time_append, time,l,freq},'TasksToExecute',3 );
start(a);
function [time]=time_append(obj,event,time,l,freq)
time_append=zeros(l,1);
last_time=time(end)
for i=1:1:l
time_append(i)=last_time+i/freq;
end
time=[time;time_append];
end
After compiling this code, I only get a time array of length 1 containing the value 0 wheras it should contain values from 0 to 3x5 =15 I think it is a stupid mistake but I can't see why. I have tried the debug mode and it seems that at the end of the line time=[time;time_append], the concatenation works but the time array is reinitialised when we go out of the function. Also I have read that callback function can't have output. Does someone would know how I could proceed? Using globals? Any other suggestion?
Thank you for reading
You can do this by using nested functions. Nested functions allow you to access "uplevel variables", and you can modify those. Here's one way to do it:
function [a, fcn] = buildTimer()
period=5;%period at which the file should be updated
freq=4;
l=freq*period;
time=0;
function time_append(~,~,l,freq)
time_append=zeros(l,1);
last_time=time(end);
for i=1:1:l
time_append(i)=last_time+i/freq;
end
time=[time;time_append];
end
function out = time_get()
out = time;
end
fcn = #time_get;
a = timer('ExecutionMode','fixedRate',...
'Period',period,...
'TimerFcn',{#time_append,l,freq},...
'TasksToExecute',3 );
start(a);
end
Note that the variable time is shared by time_append and time_get. The timer object invokes time_append, and updates time. You need to hand out the function handle time_get to retrieve the current value of time.
>> [a,fcn] = buildTimer; size(fcn()), pause(10); size(fcn())
ans =
21 1
ans =
61 1

Read specific portions of an excel file based on string values in MATLAB

I have an excel file and I need to read it based on string values in the 4th column. I have written the following but it does not work properly:
[num,txt,raw] = xlsread('Coordinates','Centerville');
zn={};
ctr=0;
for i = 3:size(raw,1)
tf = strcmp(char(raw{i,4}),char(raw{i-1,4}));
if tf == 0
ctr = ctr+1;
end
zn{ctr}=raw{i,4};
end
data=zeros(1,10); % 10 corresponds to the number of columns I want to read (herein, columns 'J' to 'S')
ctr=0;
for j = 1:length(zn)
for i=3:size(raw,1)
tf=strcmp(char(raw{i,4}),char(zn{j}));
if tf==1
ctr=ctr+1;
data(ctr,:,j)=num(i-2,10:19);
end
end
end
It gives me a "15129x10x22 double" thing and when I try to open it I get the message "Cannot display summaries of variables with more than 524288 elements". It might be obvious but what I am trying to get as the output is 'N = length(zn)' number of matrices which represent the data for different strings in the 4th column (so I probably need a struct; I just don't know how to make it work). Any ideas on how I could fix this? Thanks!
Did not test it, but this should help you get going:
EDIT: corrected wrong indexing into raw vector. Also, depending on the format you might want to restrict also the rows of the raw matrix. From your question, I assume something like selector = raw(3:end,4); and data = raw(3:end,10:19); should be correct.
[~,~,raw] = xlsread('Coordinates','Centerville');
selector = raw(:,4);
data = raw(:,10:19);
[selector,~,grpidx] = unique(selector);
nGrp = numel(selector);
out = cell(nGrp,1);
for i=1:nGrp
idx = grpidx==i;
out{i} = cell2mat(data(idx,:));
end
out is the output variable. The key here is the variable grpidx that is an output of the unique function and allows you to trace back the unique values to their position in the original vector. Note that unique as I used it may change the order of the string values. If that is an issue for you, use the setOrderparameter of the unique function and set it to 'stable'

use structure in matlab

I want to use structure in matlab but in first iteration it's run correctly and in other iteration give that message .
1x2 struct array with fields:
my code is :
for i=1:lenfd
currow=rees(i,:)
maxcn=max(currow)
if maxcn~=0
maxin=find(currow==maxcn)
ress(i).x =maxin
end
end
thank you.
That message is not a warning or error. That's just MATLAB printing the output of an operation. And it does that by default, unless you suppress it by appending a semicolon to the command:
for ii = 1:lenfd
currow = rees(ii,:); % <=== NOTE: semicolons at the end
maxcn = max(currow);
if maxcn ~= 0
ress(ii).x = find(currow==maxcn);
end
end
Note that max() may have 2 outputs, the second output being the first index into the array where the maximum occurred. If you know beforehand that any maximum will occur only once, you can skip the call to find() and use the second output of max().

troubleshooting MATLAB Iteration code

I have an iteration code which I am using to find latitude/longitude of a set of heights (h_intercept). This is a 1x79 matrix.
It works perfectly until the 22nd value. I've found that this is when h_test>h_intercept. I tried to put a condition in to reset it but it doesn't work.
When h_test>h_intercept, all of the range values become zero
For example
for j=20:40
rng_sat= sat_look_tcs_pass1(3,j);
u_sat=[sat_look_tcs_pass1(1,j)/sat_look_tcs_pass1(3,j);sat_look_tcs_pass1(2,j)/sat_look_tcs_pass1(3,j);sat_look_tcs_pass1(3,j)/sat_look_tcs_pass1(3,j)];
h_intercept=sat_look_pass1_llh(3,j)/2e3;
h_test=zeros(1,3);
rng_test_min=0;
rng_test_max=rng_sat/2e3;
err=0.01;
while abs(h_intercept-h_test)>err
rng_test=(rng_test_min+rng_test_max)/2;
tcs_test=u_sat*rng_test;
llh_test=tcs2llhT(tcs_test,station_llh);
h_test=llh_test(3,:);
if h_test>=h_intercept
rng_test_max=rng_test;
else
rng_test_min=rng_test;
end
end copter_llh(:,j)=(llh_test); h_interceptloop(:,j)=(h_intercept); end % code end
Any suggestions appreciated!
I think the error is in the first loop. In the first line you choose values 60 to 79:
h_intercept=sat_look_pass1_llh(3,60:79)/2e3;
However, you only use the length of that vector and not its values in the following code.
You iterate over the length of h_intercept, i.e. from 1 to 19:
for j=1:length(h_intercept)
which means that h_intercept=sat_look_pass1_llh(3,j)/2e3; will get the wrong value, as j ranges from 1 to 19 and not from 60 to 79.
If you change your for loop to for j=60:79, it should work ( and you can also delete the first line h_intercept=sat_look_pass1_llh(3,60:79)/2e3; )

Conditional IF/ELSE Statement in Matlab

I was trying to make a simple statement with Matlab as follows:
if TF==1
disp('One'), break
else continue
end
... ... ...
... ... ...
But even if TF is not 1, when I run the command, it doesn't CONTINUE to the rest of the script!! Any help would be appreciated-- Thanks
The continue statement has a very different meaning. Within a loop, like a for or while loop, continue instructs to skip the current round and continue with the next iteration in the loop. So if you remove continue, you will see the behavior that you are expecting. Here is an example:
for k = 1 : 10
if k == 4
% skip the calculation in the case where k is 4
continue
end
area = k * k;
disp(area);
end
When the loop iterates at k == 4, the block calculating the area of the corresponding square is skipped. This particular example is not very practical.
However, imagine you have a list of ten file names, and you want to process each file in this loop "for k = 1 : 10". You will have to try and open each file, but then if you find out the file does not exist, an appropriate way to handle it would be to print a little warning and then continue to the next file.