I have a folder containing sequential subfolders 000001_wd, 000002_wd,... in which I'm reading data contained in a file called 'plane.txt'. Some of the subfolders don't contain that file. I wish to skip them in a for-if else loop, but it is unable open file.
Tried changing or adding paths but nothing seems to work
workdir = 'D:\wass\test\output_925\';
cd(workdir)
data_frames = [1:1:37];
nframes = numel(data_frames);
V = zeros(nframes,3);
times = zeros(nframes,1);
ii=1;
prev = cd(workdir);
for frame = data_frames
fprintf('Processing frame %d\n',frame);
wdir = sprintf( '%s%06d_wd/', workdir, frame);
cd(wdir)
if exist('plane.txt')
plane_data = importdata([wdir,'plane.txt']);
times(ii) = double(ii-1)/fps;
else
times(ii) = double(ii-1)/fps;
end
ii=ii+1;
end
cd(prev);
fprintf('Saving data...\n');
I want to just continue through the loop until the last subfolder. Is there something I'm missing because the file I'm skipping is in a subfolder of my sequence?
The statement exist('plane.txt') tests to see if the file 'plane.txt' exists in the current directory. If it does, you read a file in the wdir subdirectory. Obviously, you haven't tested if that file exists.
I would simplify your code by reading the data within a try/catch block:
workdir = 'D:\wass\test\output_925\';
data_frames = 1:37; % <- don't use square brackets here, they're useless
nframes = numel(data_frames);
times = zeros(nframes,1);
for ii=1:nframes
frame = data_frames(ii);
fprintf('Processing frame %d\n',frame);
wdir = sprintf( '%s%06d_wd/', workdir, frame);
try
plane_data = importdata([wdir,'plane.txt']);
% do something with plane_data here...
catch
% ignore error
end
times(ii) = double(ii-1)/fps;
end
% ...
Note that I never used cd. You don't need to change directories to read data, and it's always better not to. The importdata statement uses an absolute path, so it does not matter what the current directory is.
A different approach involves getting a list of all files that match 'D:\wass\test\output_925\*\plane.txt':
files = dir(fullfile(workdir, '*', 'plane.txt'));
for ii=1:numel(files)
file = fullfile(files(ii).folder, files(ii).name);
plane_data = importdata(file);
% do something with plane_data here...
end
Related
I have a cell array containing file names. I want to check for the existence of all of these files in the subject folder, and if any one does not exist I wish to send a continue to the top-most for-loop (see mock code). Is there a way to do this in a one or two liner, instead of 1) using a for-loop and a double if-statement, or 2) building a function that for-loops over exist().
subjects = {'/data/subject01','/data/subject02','/data/subject03'};
files = {'a.txt','b.txt','c.txt'};
for ii = 1:numel(subjects)
for jj = 1:numel(files)
fileExists = exist([subject{ii} '/' file{jj}],'file')
if ~fileExists
continue
end
end
if ~fileExists
continue
end
% Some code to execute if all files exist.
end
The *fun functions are just loops internally and are generally slower than the explicit loop. They also very often unnecessarily obfuscate the intent and behavior of the code.
You can use ismember with all and dir to make the approach clearer and remove the unnecessary loop:
subjects = {'./data/subject01','./data/subject02'};
files = {'a.txt','b.txt','c.txt'};
for ii = 1:numel(subjects)
filelist = dir(fullfile(subjects{ii}, '*.txt'));
foundfilenames = {filelist(:).name};
if all(ismember(files, foundfilenames))
fprintf('All %u files are here: %s\n', numel(files), subjects{ii})
else
fprintf('All %u files are not here: %s\n', numel(files), subjects{ii})
end
end
With my folder structure:
/data
/subject01
a.txt
b.txt
/subject02
a.txt
b.txt
c.txt
I see the following, as expected:
All 3 files are not here: ./data/subject01
All 3 files are here: ./data/subject02
You could remove the loop by iterating over all combinations of the two arrays:
subjects = {'/data/subject01','/data/subject02','/data/subject03'};
files = {'a.txt','b.txt','c.txt'};
a=numel(subjects);
b=numel(files);
k=a*b;
paths = arrayfun(#(ii)[subjects{mod(ii-1,a)+1} '/' files{ceil(ii/b)}],1:k,'uniformoutput',0);
checkExist = cellfun(#exist, paths, repmat({'file'},1,k));
if all(checkExist)
% Some code to execute if all files exist
end
Resolved it with a cellfun and by string arrays. Technically there is still a for-loop but it resolves the double if-statement. I will leave this question open for better solutions.
subjects = {'/data/subject01','/data/subject02','/data/subject03'};
files = string({'a.txt','b.txt','c.txt'});
for ii = 1:numel(subjects)
paths = subject{ii} + files;
checkExist = cellfun(#exist, cellstr(paths), repmat({'file'},size(paths))
if ~all(checkExist(:))
continue
end
% Some code to execute if all files exist.
end
Thanks for your help.
The problem is:
I need the user to select a file based on an extension lets say .tif. I used the standard method, i.e.
[flnm,locn]=uigetfile({'*.tif','Image files'}, 'Select an image');
ext = '.tif';
But I need to fetch other image files from other subdirectories. Say the directory name returned to locn is: /user/blade/checklist/exp1/trial_1/run_1/exp001.tif. Image goes to exp100.tif.
I want to access:
/user/blade/checklist/exp1/trial_1/run_2/exp001.tif.
Also access:
/user/blade/checklist/exp1/trial_2/run_2/exp001.tif.
Up to trial_n
But if I list directory in /user/blade/checklist/exp1/, I get all folders therein from where I can reconstruct the right path. The naming structure is orderly.
My current solution is
[flnm,locn]=uigetfile({'*.tif','Image files'}, 'Select an image');
ext = '.tif';
parts = strsplit(locn, '/');
f = fullfile(((parts{end-5}),(parts{end-4}),(parts{end-3}),(parts{end-2}),(parts{end-1}));
Which is really ugly and I also lose the first /. Any help is appreciated.
Thanks!
First, get the file location as you did; note a small change I've made to make use of the variable ext.
ext = '.txt';
[flnm,locn]=uigetfile({['*',ext]}, 'Select an image');
parts = strsplit(locn,'/');
root = parts(1:end-4);
parts has 2 information - 1) path of the selected file; 2) path of your working folder, checklist, which you need. So root has the working folder.
Then, list out all the files you wanted, and put them in a cell array.
The file names should contain partial (subfolder) paths; it's not difficult to follow the pattern.
flist = {'trial_1/run_1/exp001.tif', ...
'trial_1/run_1/exp002.tif', ...
'trial_1/run_2/exp001.tif', ...
'trial_2/run_1/exp001.tif', ...
'trial_2/run_2/exp001.tif'};
I just enumerated a few; you can use a for loop to automatically generate trial_n and expxxx.tif. An example code to generate the complete file list (but not "full paths") -
flist = cell(10*2*100,1);
for ii = 1:10
for jj = 1:2
for kk = 1:100
flist{sub2ind([10,2,100],ii,jj,kk)} = ...
sprintf('trial_%d/run_%d/exp%03d%s', ii,...
jj, kk, ext);
end
end
end
Finally, use strjoin to concatenate the first part (your working folder) and second part (needed files in subfolders). Use cellfun to call strjoin for each cell in the file list cell array, so for every file you want you get a full path.
full_flist = cellfun(#(x) strjoin([root, x],'/'), ...
flist, 'UniformOutput', false);
Example output -
>> locn
locn =
/home/user/Downloads/exp1/trial_1/run_1/
>> for ii = 1:5
full_flist{ii}
end
ans =
/home/user/Downloads/trial_1/run_1/exp001.tif
ans =
/home/user/Downloads/trial_1/run_1/exp002.tif
ans =
/home/user/Downloads/trial_1/run_2/exp001.tif
ans =
/home/user/Downloads/trial_2/run_1/exp001.tif
ans =
/home/user/Downloads/trial_2/run_2/exp001.tif
>>
Note: You can either use
strjoin(str1, str2, '/')
or
sprintf('%s/%s', str1, str2)
They are equivalent.
I have a simple question but I don't know how to solve it.
I want to process all the files in a folder and I want to write the output values on a separate line on a matrix. After direct the folder and get the list of the files and their names
filePattern=fullfile( myPath,'*.txt')
I applied a 'loop'. To save the results on each line for every file, this is what I'm doing but it doesn't work (the code works with one file, not with all of them).
text= {baseFileName, result2b, result3b, result4b, result5b};
Is there something wrong?
Thanks in advance! Greetings,
Emma
PD)
myPath = 'C:\SP\';
% if ~isdir(myPath)
% errorMessage = sprintf('Error: The following folder does not exist:\n%s', myFolder);
% uiwait(warndlg(errorMessage));
% return;
a= dir (fullfile(myPath,'*.DIM')); %
fileNames = { a.name };
filePattern=fullfile( myPath,'*.txt');
txtFiles= dir(filePattern);
for k = 1:length(txtFiles)
baseFileName=txtFiles(k).name;
fullFileName= fullfile(myPath,baseFileName);
fid=fopen(fullFileName, 'r+');
for i = 1:18
m{i} = fgetl(fid);
end
result2 = m{18};
result2b= result2([12:19]);
(...)
EDIT:
I added a screenshoot about my variables. Is it possible because of the txtFiles is wrong?
I'm trying to load several .mat files to the workspace. However, they seem to overwrite each other. Instead, I want them to append. I am aware that I can do something like:
S=load(file1)
R=load(file2)
etc.
and then append the variables manually.
But there's a ton of variables, and making an append statement for each one is extremely undesirable (though possible as a last resort). Is there some way for me to load .mat files to the workspace (by using the load() command without assignment) and have them append?
Its not entirely clear what you mean by "append" but here's a way to get the data loaded into a format that should be easy to deal with:
file_list = {'file1';'file2';...};
for file = file_list'
loaded.(char(file)) = load(file);
end
This makes use of dynamic field references to load the contents of each file in the list into its own field of the loaded structure. You can iterate over the fields and manipulate the data however you'd like from here.
It sounds like you have a situation in which each file contains a matrix variable A and you want to load into memory the concatenation of all these matrices along some dimension. I had a similar need, and wrote the following function to handle it.
function var = loadCat( dim, files, varname )
%LOADCAT Concatenate variables of same name appearing in multiple MAT files
%
% where dim is dimension to concatenate along,
% files is a cell array of file names, and
% varname is a string containing the name of the desired variable
if( isempty( files ) )
var = [];
return;
end
var = load( files{1}, varname );
var = var.(varname);
for f = 2:numel(files),
newvar = load( files{f}, varname );
if( isfield( newvar, varname ) )
var = cat( dim, var, newvar.(varname) );
else
warning( 'loadCat:missingvar', [ 'File ' files{f} ' does not contain variable ' varname ] );
end
end
end
Clark's answer and function actually solved my situation perfectly... I just added the following bit of code to make it a little less tedious. Just add this to the beginning and get rid of the "files" argument:
[files,pathname] = uigetfile('*.mat', 'Select MAT files (use CTRL/COMM or SHIFT)', ...
'MultiSelect', 'on');
Alternatively, it could be even more efficient to just start with this bit:
[pathname] = uigetdir('C:\');
files = dir( fullfile(pathname,'*.mat') ); %# list all *.mat files
files = {files.name}'; %# file names
data = cell(numel(files),1); %# store file contents
for i=1:numel(files)
fname = fullfile(pathname,files{i}); %# full path to file
data{i} = load(fname); %# load file
end
(modified from process a list of files with a specific extension name in matlab).
Thanks,
Jason
i wrote a code that analyze a video file and then plot data on a graph then
save this graph into
excel and jpg.
but my problem is that i have more than 200 video to analyze in around 20 folder,
so i need to automate this code to loop inside folders and analyze each *.avi file inside and
.. So any ideas or suggestions
Really appreciate your help
I need to know how to loop folders and get files inside and the apply a function to these files in that folder
Please note that my function that i also want to save graph result to img, should i then include full path while saving ? and how can i do it ?
The dir and fullfile commands are what you need. Depending on your directory structure, something like this:
video_dir = 'videos';
% I'm not sure if there's a way to directly get a list of directories, but
% this will work
video_dir_children = dir(video_dir);
video_subdirs = [];
for ix = 1 : length(video_dir_children),
% note we're careful to kick out '.' and '..'
% (and any other directory starting with a '.')
if(video_dir_children(ix).isdir && video_dir_children(ix).name(1) ~= '.')
video_subdirs = [video_subdirs; video_dir_children(ix)];
end
end
for ix = 1 : length(video_subdirs),
this_dir = fullfile(video_dir, video_subdirs(ix).name);
avi_files_in_this_dir = dir(fullfile(this_dir, '*.avi'));
for jx = 1 : avi_files_in_this_dir,
doVideoProcessing(fullfile(this_dir, avi_files_in_this_dir(jx).name));
end
end