Why does my loop only run on the first file in the folder?I'm new to matlab and programming.

1 view (last 30 days)
function [] = Sai_HalfMaxtimes();
pn = uigetdir(pwd, 'matlab');
cont = dir([pn, '\*.csv']);
for bctr = 1:length(cont)
fn = cont(bctr).name;
singlefile(fn)
end
function [] = singlefile(fn);
end

Accepted Answer

dpb
dpb on 4 May 2017
Edited: dpb on 4 May 2017
Dunno, can't see your terminal from here... :)
First guess is that length(cont) is 1.
Set a breakpoint in the editor and use the debugger to step through the code and see what you get returned for the dir().
ADDENDUM
Ah!
delimiter = ',';
startRow = 25;
fmt=[repmat('%s',1,2) '%*[^\n]'];
for bctr =1:length(cont)
iterationString=['Iteration #', int2str(bctr)];
fn = cont(bctr).name;
singlefile(fn)
end
You've done the whole loop here...leaving fn at whatever is the last element in cont array is. You called the function singlefile for each element in turn, but it has no discernible effects as it returns nothing.
Then, after you finish the loop, you add a whole bunch of additional code that probably should have a significant portion of it inside the loop.
Structure looks like should be something like--
function = Sai_HalfMaxtimes();
% set fixed parameters
delimiter = ',';
startRow = 25;
fmt=[repmat('%s',1,2) '%*[^\n]'];
% scan directory requested
pn = uigetdir(pwd, 'matlab');
d=dir(fullfile(pn, '*.csv'));
% loop over found files
for i=1:length(d)
fid=fopen(d(i).name,'r');
dataArray = textscan(fid, fmt, 'Delimiter', delimiter, ...
'headerlines', startRow, ...
'ReturnOnError', false);
fid=fclose(fid);
%%Allocate imported array to column variable names
Time_Hrs = dataArray{:, 1};
Resis_Cap = dataArray{:, 2};
Time_Hrs1=str2double(Time_Hrs);
Resistance_Ohm1=str2double(Resis_Cap);
%Plot Orginal Figure
figure( 'Name', 'Orig' );
h = plot( Time_Hrs1, Resistance_Ohm1);
legend( h, 'RorC vs Time', 'untitled fit 1', 'Location', 'NorthEast' );
% Perform the 1/2 Time Operation
MaxHalf= max(Resistance_Ohm1)/2; %value to find
Max= max(Resistance_Ohm1)
tmp = abs(Resistance_Ohm1-MaxHalf);% Taking the capicitance values and subtracting the 1/2 max from the vector
[minimum idx] = min(tmp); %index of closest value, finding the row at which the value is closest to 0
Time_Half = Time_Hrs1(idx) %closest time;
% Label axes with half max
xlabel('Time(hrs)')
ylabel('ResistanceorCapacitance')
grid on
deriv=h
hold on
plot([Time_Half,Time_Half], [0,MaxHalf]);
str= ('Half-max');
text(Time_Half,MaxHalf, str)
end
Not knowing what the file structure actually looks like, I'd guess you could clean the read up quite a lot yet by actually reading numeric rather than string variables.
The import tool generated code is pretty klunky; I removed the first call and substituted the 'headerlines' option for it amongst some other cleanups that looked to be warranted.
  5 Comments
dpb
dpb on 5 May 2017
It's just looping over each element in the directory structure d, sequentially opening and reading each file in turn.
textscan and friends such as fscanf from which it is descended are C-like routines that use a "file handle" to access the physical file. fopen is the tool which returns this magic number which is a link to the physical file that the actual i/o functions use. (Some higher-level functions like importdata hide this by accepting an actual file name, but internally they operate the same way.)
The rest is just some of the myriad optional parameters for textscan; they should be pretty-much self-explanatory by the name what their function is.
The fmt variable is the format string that maps the content of the file to the data variables you want returned--above it is two string variables and then an idiom to skip the rest of each record (line).
As I noted, this is certainly not the most efficient way to have read the file; I infer this was generated by the code-generation from the import tool; it almost always generates far less than optimum code than one could write simply by inspection of the file. By doing this, all the references following first have to convert the string values to numeric (the stuff leading up to str2double calls; it would have been much more efficient to write
fmt=[repmat('%f',1,2) '%*[^\n]'];
data=cell2mat(textscan(fid,fmt,'Delimiter',;,;, ...
'headerlines', startRow, ...
'collectoutput',1));
after which you would have a 2D array data with the first two columns from the file. In general in Matlab it's preferable to use such arrays and write things like
hL=plot(data(:,1), data(:,2));
rather than creating too many named variables altho here with simply an X and Y, that's not bad; it's when folks write X1, X2, X3, ... they begin to get into real trouble.
The cell2mat in the above is another powerful "trick" -- textscan is quite powerful but it has one drawback for relatively simple cases such as this--it returns only cell arrays. They're useful for holding disparate data, but when everything is numeric as here, then they're way overkill and one has to use the "curlies" {} to dereference the content instead of just (). I prefer to eliminate that and just cast directly to double as part of the read operation.
Again, far more than you asked, undoubtedly... :)
PS: You might check you got the first row of data you expected; it's possible the line count for 'headerlines' is one more than should be owing to the way importdata generated its code. If you're missing that first line, just fixup that value to skip one less line.
dpb
dpb on 5 May 2017
Edited: dpb on 5 May 2017
"The fmt variable is the format string..."
fmt=[repmat('%f',1,2) '%*[^\n]'];
NB:
I used repmat here deliberately to illustrate another Matlab idiom--since there are only two repeated format strings here it's overkill but the general syntax is very useful to eliminate the ugliness of stuff like the auto-generated string the above replaced--
formatSpec = '%s%s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%[^\n\r]';
How many of which are in the above?--_terrible_ mess to read/write/maintain that way. Building it as above in pieces is much cleaner.
Unfortunately, the inventors of C which Matlab uses for its i/o model had the "not invented here" complex and instead of following the already well-established FORTRAN FORMAT statement form, they developed their own flavor which can't accept a repeat count. We've been stuck with such abominations ever since. :(

Sign in to comment.

More Answers (1)

Randy st
Randy st on 5 May 2017
it works! THanks!

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!