calling file defined by variables and wildcard - matlab

I am attempting to loop through folders, defined by variables, and select a single file, defined by a wildcard (in matlab R2012a). An example file would be: /folder1/folder2/601/mprage/xyz.nii. In researching this, I've tried to incorporate the variables and wildcard via dir and fullfile, but am getting a horzcat (conversion to struct from char is not possible) error. Ultimately, the file would be processed by the function 'callspmsegmentation'. I am new to matlab programming... Here is my script:
clear all
studyDir = '/folder1/folder2';
anatDir = 'mprage';
subjects = {'601', '602', '603'};
for jSubj = 1:length(subjects)
niiname = dir(fullfile(studyDir, subjects{jSubj}, anatDir, '*.nii'));
nii = [studyDir '/' subjects{jSubj} '/' anatDir '/' niiname];
callspmsegmentation(nii);
end
Alternatively, I tried the more direct: (which also didn't work)
clear all
studyDir = '/folder1/folder2';
anatDir = 'mprage';
subjects = {'601', '602', '603'};
for jSubj = 1:length(subjects)
nii = [studyDir '/' subjects{jSubj} '/' anatDir '/*.nii'];
callspmsegmentation(nii);
end

The output of dir is a struct not a string, so you must access the name field to get the filename
niiname = dir(fullfile(studyDir, subjects{jSubj}, anatDir, '*.nii'));
nii = [studyDir '/' subjects{jSubj} '/' anatDir '/' niiname.name];
I would also probably re-write it to use fullfile so that you don't hard-code all of those file separators. Something like this should work.
% Store the folder name
folder = fullfile(studyDir, subjects{jSubj}, anatDir);
% Get the file listing
file = dir(fullfile(folder, '*.nii'));
% Append the folder to the filename
nii = fullfile(folder, file.name);
% Process the file
callspmsegmentation(nii);

Related

how skip some specific files in multiple subfolders in matlab?

I need to skip some specific files in different sub-folders. So I tried by line "if filename" in the snippet that if the filename not contains raw, info, do some operations, but it doesn't work. I really appreciate if someone can point me in the right direction how can I skip these filenames which does have specific character like "raw" or "info."..
input_dirName = dir('D:\Neda\Pytorch\CAMUS\training\');
Output_dirName = 'D:\Neda\Pytorch\CAMUS\data\';
GT_dirName = 'D:\Neda\Pytorch\CAMUS\GT\';
dirName = 'D:\Neda\Pytorch\CAMUS\training\';
fileList = SureScan_getAllFiles(dirName);
foldername = fullfile({input_dirName.folder}, {input_dirName.name});
foldername = foldername(3:end);
for k = 1:length(fileList)-50
filename = fileList{k};
if filename ~= contains(filename,'raw') | filename ~= contains(filename,'Info_') | filename ~= contains(filename,'sequence.mhd')| filename ~=contains(filename,'_sequence')
% do some operation
end
end
The output of contains is either true or false and hence it will never be equal to any filename.
To skip filenames that have any of 'raw', 'Info_', 'sequence.mhd' or '_sequence', use:
if ~contains(filename, {'raw', 'Info_', 'sequence.mhd', '_sequence'})
%do some operation
end

Faster copyfiles Matlab

I have a folder origin_training with subfolders like FM, folder1, folder2, ... . I can get the list of image files in .png format into a cell called FM.
FM_dir = fullfile(origin_training, 'FM');
FM = struct2cell(dir(fullfile(FM_dir, '*.png')))';
My goal is to match the names in my folder with the images in my cd, and make a new folder FM with the images from cd. Image names in the two paths are identical. I can do that with:
% mother_folder = '...' my current directory
filenames = FM(:,1);
destination = fullfile(mother_folder, 'FM', FM(:,1));
cellfun(#copyfile,filenames, destination);
This is really slow. Takes minutes even for small amounts of images (~30).
My current directory has ~ 10000 images (the ones that correspond to FM, folder2, folder3, ...). What am I missing here?
An alternative would be to create a shell command and execute it. Assuming FM contains full paths for each file, or relative paths from the current directory, then:
FM_dir = fullfile(origin_training, 'FM');
destination = fullfile(mother_folder, 'FM');
curdir = cd(FM_dir);
FM = dir('*.png');
cmd = ['cp ', sprintf('%s ',FM.name), destination];
system(cmd);
cd(curdir);
If you're on Windows, replace 'cp' by 'copy'.
Note that here we're not creating a shell command per file to be copied (presumably what copyfile does), but a single shell command that copies all files at once. We're also not specifying the name for each copied file, we specify the names of the files to be copied and where to copy them to.
Note also that for this to work, mother_folder must be an absolute path.
I somehow put my code into a function and now it works at expected speed. I suspected that cd had to do with the low speed so I am only passing the full directories as character vectors.
The same approach works for my purpose or with a slight modification to just copy from A to B. As now, it works to match files in A to those on B and copy to B/folder_name
function [out] = my_copyfiles(origin_dir, folder_name, dest_dir, extension)
new_dir = fullfile(origin_dir, folder_name);
% Get a cell with filenames in the origin_dir/folder_name
% Mind transposing to have them in the rows
NEW = struct2cell(dir(fullfile(new_dir, extension)))';
dest_folder = fullfile(dest_dir, folder_name);
% disp(dest_folder)
if ~exist(dest_folder, 'dir')
mkdir(dest_folder)
end
%% CAUTION, This is the step
% Use names from NEW to generate fullnames in dest_dir that would match
filenames = fullfile(dest_dir, NEW(:,1));
destination = fullfile(dest_folder, NEW(:,1));
% if you wanted from origin, instead run
% filenames = fullfile(new_dir, NEW(:,1));
% make the copies
cellfun(#copyfile,filenames, destination);
%Save the call
out.originDir = new_dir;
out.copyFrom = dest_dir;
out.to = dest_folder;
out.filenames = filenames;
out.destination = destination;
end

Matlab | How to load/use files with consecutive names (abc1, abc2, abc3) and then pass on to the next series (cba1, cba2, cba3)?

I have a folder containing a series of data with file names like this:
abc1
abc2
abc3
bca1
bca2
bca3
bca4
bca5
cba1
... etc
My goal is to load all the relevant files for each file name, so all the "abc" files, and plot them in one graph. Then move on to the next file name, and do the same, and so forth. Is there a way to do this?
This is what I currently have to load and run through all the files, grab the data in them and get their name (without the .mat extension) to be able to save the graph with the same filename.
dirName = 'C:\DataDirectory';
files = dir( fullfile(dirName,'*.mat') );
files = {files.name}';
data = cell(numel(files),1);
for i=1:numel(files)
fname = fullfile(dirName,files{i});
disp(fname);
files{i} = files{i}(1:length(files{i})-4);
disp(files{i});
[Rest of script]
end
You already found out about the cool features of dir, and have a cell array files, which contains all file names, e.g.
files =
'37abc1.mat'
'37abc2.mat'
'50bca1.mat'
'50bca2.mat'
'1cba1.mat'
'1cba2.mat'
The main task now is to find all prefixes, 37abc, 50bca, 1cba, ... which are present in files. This can be done using a regular expression (regexp). The Regexp Pattern can look like this:
'([\d]*[\D]*)[\d]*.mat'
i.e. take any number of numbers ([\d]*), then any number of non-numeric characters ([\D]*) and keep those (by putting that in brackets). Next, there will be any number of numeric characters ([\d]*), followed by the text .mat.
We call the regexp function with that pattern:
pre = regexp(files,'([\d]*[\D]*)[\d]*.mat','tokens');
resulting in a cell array (one cell for each entry in files), where each cell contains another cell array with the prefix of that file. To convert this to a simple not-nested cell array, we call
pre = [pre{:}];
pre = [pre{:}];
resulting in
pre =
'37abc' '37abc' '50bca' '50bca' '1cba' '1cba'
To remove duplicate entries, we use the unique function:
pre = unique(pre);
pre =
'37abc' '50bca' '1cba'
which leaves us with all prefixes, that are present. Now you can loop through each of these prefixes and apply your stuff. Everything put together is:
% Find all files
dirName = 'C:\DataDirectory';
files = dir( fullfile(dirName,'*.mat') );
files = {files.name}';
% Find unique prefixes
pre = regexp(files,'([\d]*[\D]*)[\d]*.mat','tokens');
pre = [pre{:}]; pre = [pre{:}];
pre = unique(pre);
% Loop through prefixes
for ii=1:numel(pre)
% Get files with this prefix
curFiles = dir(fullfile(dirName,[pre{ii},'*.mat']));
curFiles = {curFiles.name}';
% Loop through all files with this prefix
for jj=1:numel(curFiles)
% Here the magic happens
end
end
Sorry, I misunderstood your question, I found this solution:
file = dir('*.mat')
matching = regexp({file.name}, '^[a-zA-Z_]+[0-9]+\.mat$', 'match', 'once'); %// Match once on file name, must be a series of A-Z a-z chars followed by numbers.
matching = matching(~cellfun('isempty', matching));
str = unique(regexp(matching, '^[a-zA-Z_]*', 'match', 'once'));
str = str(~cellfun('isempty', str));
group = cell(size(str));
for is = 1:length(str)
ismatch = strncmp(str{is}, matching, length(str{is}));
group{is} = matching(ismatch);
end
Answer came from this source: Matlab Central

Save data as modified input file name

I have a program that loads data from a .txt file and performs some curve fitting. The input file name for this example is experiment09.txt.
After processing I want to save a variable with the same input filename but appended with something like _fit. So my saved workspace variable in this case would be experiment09_fit.txt.
I have gotten this far in MATLAB:
buf = length(filename)
saveName = filename(1:buf-7)
which gives me a saveName of experiment09 but I am at a loss as to how to add my chosen string on the end to make it experiment09_fit. Once I have a valid save name I will then just call
save(saveName, 'fittedValue', '-ASCII');
Help would be greatly appreciated.
What about this:
filename = 'experiment09.txt';
[pathstr, basename, ext] = fileparts(filename);
outname = [basename, '_fit', ext]; % will give 'experiment09_fit.txt'
Also use string concatenation for adding additional names to string variables.
For example,
filename = 'experiment09.txt';
[pathstr, name, ext] = fileparts(filename);
outputName1 = strcat(name,'_fit.');
outputName = strcat(outputName1,ext);

process a list of files with a specific extension name in matlab

How can I process all the files with ".xyz" extension in a folder? The basic idea is that I want a list of file names and then a for loop to load each file.
As others have already mentioned, you should use the DIR function to list files in a directory.
If you are still looking, here is an example to show how to use the function:
dirName = 'C:\path\to\folder'; %# folder path
files = dir( fullfile(dirName,'*.xyz') ); %# list all *.xyz files
files = {files.name}'; %'# file names
data = cell(numel(files),1); %# store file contents
for i=1:numel(files)
fname = fullfile(dirName,files{i}); %# full path to file
data{i} = myLoadFunction(fname); %# load file
end
Of course, you would have to supply the function that actually reads and parses the XYZ files.
Use dir() to obtain a list of filenames. You can specify wildcards.
You could use
fileName=ls('*xyz').
fileName variable will have the list of all the filenames which you can use in the for loop
Here is my answer:
dirName = 'E:\My Matlab\5';
[sub,fls] = subdir(dirName);
D = [];
j = 1;
for i=1:length(sub),
files{i} = dir( fullfile(sub{i},'*.xyz') );
if length(files{i})==1
D(j) = i;
files_s{j} = sub{i};
j=j+1;
end
end
varaible files_s returns the desire paths that contain those specific data types!
The subdir function can be found at:
http://www.mathworks.com/matlabcentral/fileexchange/1492-subdir--new-