MATLAB: extracting onsets in different files and saving them in different files - matlab

My MATLAB script is to:
Extract four different fMRI onsets from MATLAB files (the files are named 'subject 06 data', 'subject 05 data', etc.)
Put this information in a new file with two other variables named 'durations' and 'names'.
Save all this as a new MATLAB file.
I am facing two problems:
At the moment, the script below manages to do steps 1 through 3 for the first MATLAB file in the directory 'Gender_recogntion', but it does not do 1 through 3 for the other MATLAB files in the folder. It crashes in the loop at the line 'load(sub_name(i).name);'.
This is the error I get:
??? Improper index matrix reference.
Error in ==> Gender_onsets_script_2 at 16
load(sub_name(i).name);
In addtion, I would like to name the new MATLAB files with the name of the original MATLAB files. At the moment, the new MATLAB files is named 'onsets.mat'.
clear all
close all
clc
cd 'C:\Program Files\MATLAB\R2007b\Data\Resilience\Real_data\Raw\Matlab_files\Gender_recogntion';
sub_name = dir('C:\Program Files\MATLAB\R2007b\Data\Resilience\Real_data\Raw\Matlab_files\Gender_recogntion\*.mat');
for i = 1:numel(sub_name);
load(sub_name(i).name);
names = {'sad' 'anger' 'neutral' 'rest'};
durations = {[18] [18] [18] [18]};
onsets=cell(1,4);
onsets{1} = data.time_since_scan_start(data.emotion==5)/1000; %Get the 36 onsets for sad.
onsets{2} = data.time_since_scan_start(data.emotion==4)/1000; %Get the 36 onsets for anger.
onsets{3} = data.time_since_scan_start(data.emotion==6)/1000;% Get the 36 onsets for calm.
onsets{4} = datarest.onset/1000; %Get the six onsets for the rest blocks.
onsets{1} = onsets{1}(1:6:36)'; %Get the first onset value of each of the six blocks.
onsets{2} = onsets{2}(1:6:36)';
onsets{3} = onsets{3}(1:6:36)';
onsets{4} = onsets{4}';
%cd Onsets folder, saves onsets, and then cd back to folder "Matlab_files"
cd 'C:\Program Files\MATLAB\R2007b\Data\Resilience\Real_data\Onsets';
save 'onsets.mat' names durations onsets
cd 'C:\Program Files\MATLAB\R2007b\Data\Resilience\Real_data\Raw\Matlab_files\Gender_recogntion';
end

For your second question about naming the output files the same as the input, you can use the function version of save and pass in the variable sub_name(i).name as the filename argument.
save(sub_name(i).name, 'names', 'durations', 'onsets')
This uses the exact same name for input and output (in different directories, in your script). When I save output files, I typically keep them in the same directory as the inputs, so I modify an input filename with regular expressions (see regexprep) or adding a prefix or suffix (strcat) to create a related but distinct output filename.
For future reference...the default filetype for save is MATLAB data format; you could pass in '-ASCII' as an argument to save as a text file if your data types were compatible. The cell arrays in this example aren't, but strings and numerical matrices would be, so if text output files were important, you could use alternate data structures from the beginning or convert cells with cell2mat. A generic example with the save() version: save(filename, '-ASCII', 'x', 'y','z') where x,y,z are ASCII-friendly variables and filename is a text file.
[additional response, adding Jan 5, 2011]
About your first question on the error message:
??? Improper index matrix reference.
Is it possible that a saved .mat file contains a variable named dir, that would override the standard directory-listing function and cause that error? I read that tip on another site, just wanted to pass it along in case it helps.

Related

Taking symbolic variables out of txt file and making a matrix in Matlab

I have a txt file containing following characters.
theta1 , l1 and others are symbolic variables.( Don't mind about it)
M=[theta1 + (l1^2*m1)/4 + l1^2*m2 (l1*l2*m2*cos(fi1 - fi2))/2 ;
(l1*l2*m2*cos(fi1 - fi2))/2 theta2 + (l2^2*m2)/4 ]
I need to take it out and make it a symbolic matrix. As you can see txt file is already fine for making matrix but I don't want to copy paste the whole thing to script, I rather want to do it automatically.
fid = fopen('a.txt');
MMatrix=textscan(fid,'%s');
fclose(fid);
I tried the code above but it turn out to be not useful. What do you think is the way to copy the whole thing and use it for matrix making?
Instead of reading that as a string or a character array and then possibly resorting to evil (eval) method, just rename the extension from txt to m since you already have your arrays defined in the MATLAB way in the text files. Maintain a backup copy of those original txt files if needed.
If it is a single file (a.txt), you can rename it manually or with this code to a.m:
movefile('a.txt', 'a.m');
If there are multiple such files in a directory then you can use the following code to change the extension of all such txt files in the current directory:
txtfiles = dir('*.txt'); %getting all txt files in the current directory
for num = 1:numel(txtfiles)
[~, fname] = fileparts(txtfiles(num).name); %filename (without extension)
movefile(txtfiles(num).name, [fname,'.m']); %renaming
end
Now you can simply use the name of the respective file in your script to get whatever arrays that file have in it.

How do you call a function that takes in a MAT file, manipulate the data in that file, and create a new textfile with that same MAT file name?

The filename in question is a MAT file that contains elements in the form of "a - bi" where 'i' signifies an imaginary number. The objective is to separate the real, a, and imaginary, b, parts of these elements and put them into two arrays. Afterwards, a text file with the same name as the MAT file will be created to store the data of the newly created arrays.
Code:
function separate(filename)
realArray = real(filename)
imagArray = imag(filename)
fileIDname = strcat(filename, '.txt')
fileID = fopen(fileIDname, 'w')
% more code here - omitted for readability
end
I am trying to run the above code via command window. Here's what I've tried so far:
%attempt 1
separate testFileName
This does not work as the output does not contain the correct data from the MAT file. Instead, realArray and imagArray contains data based on the ascii characters of "testFileName".
e.g. first element of realArray corresponds to the integer value of 't', the second - 'e', third - 's', etc. So the array contains only the number of elements as the number of characters in the file name (12 in this case) instead of what is actually in the MAT file.
%attempt 2
load testFileName
separate(testFileName)
So I tried to load the testFileName MAT variable first. However this throws an error:
Complex values cannot be converted to chars
Error in strcat (line 87)
s(1:pos) = str;
Error in separate (line xx)
fileIDname = strcat(filename, '.txt')
Basically, you cannot concatenate the elements of an array to '.txt' (of course). But I am trying to concatenate the name of the MAT file to '.txt'.
So either I get the wrong output or I manage to successfully separate the elements but cannot save to a text file of the same name after I do so (an important feature to make this function re-usable for multiple MAT files).
Any ideas?
A function to read complex data, modify it and save it in a txt file with the same name would look approximately like:
function dosomestuff(fname)
% load
data=load(fname);
% get your data, you need to knwo the variable names, lets assume its call "datacomplex"
data.datacomplex=data.datacomplex+sqrt(-2); % "modify the data"
% create txt and write it.
fid=fopen([fname,'.txt'],'w');
fprintf(fid, '%f%+fj\n', real(data.datacomplex), imag(data.datacomplex));
fclose(fid);
There are quite few assumptions on the data and format, but can't do more without extra information.

Loading multiple .mat files containing the same variable name and changing the variable names simultaneously?

So I have a directory that has many .mat files:
apples.mat, oranges.mat, bananas.mat, grapes.mat, apricots.mat, pears.mat, pineapple.mat
All of these .mat files has a variable name "calories" assigned a value. How do I load all of these .mat files simultaneously in MATLAB and change the variables for each one from calories to calories_(fruit name) so that I can have all the variable values in the workspace to play with?
For example, I want to load apples.mat and change its variable name from calories to calories_apple, then load oranges.mat and change is variable name from calories_orange, etc. without doing it all manually.
I know it's something along the lines of creating a string with the different fruit names, and the indexing along the string to load a file and change its variable from variable to variable_%s with the %s indicating the fruit content generated along the loop. It's a big mess for me, however, I don't think I'm structuring it right. Would anyone care to help me out?
I would load each .mat file in sequence and put each of the corresponding calories as a separate field being all combined into a single struct for you to access. Given the directory of where these .mat files appear, do something like this:
%// Declare empty structure
s = struct()
folder = '...'; %// Place directory here
%// Get all MAT files in directory
f = dir(fullfile(folder, '*.mat'));
%// For each MAT file...
for idx = 1 : numel(f)
%// Get absolute path to MAT file - i.e. folder/file.mat
name = fullfile(folder, f(idx).name);
%// Load this MAT file into the workspace and get the calories variable
load(name, 'calories');
%// Get the name of the fruit, are all of the characters except the last 4 (i.e. .mat)
fruit_name = f(idx).name(1:end-4);
%// Place corresponding calories of the fruit in the structure
s.(['calories_' fruit_name]) = calories;
end
You can then access each of the calories like so using dot notation:
c = s.calories_apple;
d = s.calories_orange;
...
...
... and so on.
I am assuming that you do not mean to include the parenthesis in calories_(fruit name). I am also assuming there are no other .mat files in your current directory. This should do the trick:
theFiles = dir('*.mat');
for k = 1:length(theFiles)
load(theFiles(k).name, 'calories');
eval(['calories_' theFiles(k).name(1:length(theFiles(k).name)-4) ' = calories;'])
clear calories
end
Let me know if this helps or not.
EDIT
As, rayryeng points out. The use of eval is, apparently, a bad practice. So, if you are willing to change the way you are thinking about the problem, I suggest you use a structure. In which case, rayryeng's response would be an acceptable answer, even though it does not directly answers your original question.

MATLAB: Use a variable with a file extenstion to load files

I am using MATLAB
I Have 51 files in their own directory all of .out extention created by a seperate program, all numbered 0 to 50.
ie
0.out
1.out
2.out
and so on til 50.out.
I need to load each file 1 by one to do calculations upon them within a for loop. How would I do this using the count variable to load the file, if the directory is set beforehand?
i.e.
%set directiory
cd(......)
%for loop
For count = 0:50,
data = count.out *<-----this line*
.....
Many thanks!
First generate the file name with
fileName = [int2str(count) '.out'];
then open the file with
fid = fopen(fileName, 'r');
The loading phase depends on the kind of file you want to read. Assuming it is a text file you can, for example, read it line after line with
while ~feof(fid)
line = fgetl(fid);
end
or use more specialized functions (see http://www.mathworks.it/it/help/matlab/text-files.html). Before the end of the for loop you'll have to close the file by calling
fclose(fid);
Another quite nice way to do it is to use the dir function
http://www.mathworks.co.uk/help/matlab/ref/dir.html
a = dir('c:\docs*.out')
Will give you a structure containing all the info about the *.out files in the directory you point it to, (or the path). You can then loop through it bit by bit. using fopen or csvread or whatever file reading function you want to use.

How do I sort files into multiple folders in MATLAB?

I am little stuck on a problem. I have tons of files generated daily and I need to sort them by file name and date. I need to do this so my MATLAB script can read them. I currently do this manually, but was wondering if there is a easier way in MATLAB to sort and copy files.
My file names look like:
data1_2009_12_12_9.10
data1_2009_12_12_9.20
data1_2009_12_12_9.30
data1_2009_12_12_9.40
data2_2009_12_12_9.10
data2_2009_12_12_9.20
data2_2009_12_12_9.30
data2_2009_12_12_9.40
data3_2009_12_12_9.10
data3_2009_12_12_9.20
data3_2009_12_12_9.30
data3_2009_12_12_9.40
...
and tons of files like this.
Addition to above problem :
There has to be a easier way to stitch the files together.
I mean copy file
' data1_2009_12_12_9.20' after file 'data1_2009_12_12_9.10' and so on ,...
such that i am left with a huge txt file in end named data1_2009_12_12 ( or what ever ). containing all the data stitched together.
Only way now i know to do is open all files with individual dlmread command in matlab and xls write one after another ( or more trivial way of copy paste manually )
Working in the field of functional imaging research, I've often had to sort large sets of files into a particular order for processing. Here's an example of how you can find files, parse the file names for certain identifier strings, and then sort the file names by a given criteria...
Collecting the files...
You can first get a list of all the file names from your directory using the DIR function:
dirData = dir('your_directory'); %# Get directory contents
dirData = dirData(~[dirData.isdir]); %# Use only the file data
fileNames = {dirData.name}; %# Get file names
Parsing the file names with a regular expression...
Your file names appear to have the following format:
'data(an integer)_(a date)_(a time)'
so we can use REGEXP to parse the file names that match the above format and extract the integer following data, the three values for the date, and the two values for the time. The expression used for the matching will therefore capture 6 "tokens" per valid file name:
expr = '^data(\d+)\_(\d+)\_(\d+)\_(\d+)\_(\d+)\.(\d+)$';
fileData = regexp(fileNames,expr,'tokens'); %# Find tokens
index = ~cellfun('isempty',fileData); %# Find index of matches
fileData = [fileData{index}]; %# Remove non-matches
fileData = vertcat(fileData{:}); %# Format token data
fileNames = fileNames(index); %# Remove non-matching file names
Sorting based on the tokens...
You can convert the above string tokens to numbers (using the STR2DOUBLE function) and then convert the date and time values to a date number (using the function DATENUM):
nFiles = size(fileData,1); %# Number of files matching format
fileData = str2double(fileData); %# Convert from strings to numbers
fileData = [fileData zeros(nFiles,1)]; %# Add a zero column (for the seconds)
fileData = [fileData(:,1) datenum(fileData(:,2:end))]; %# Format dates
The variable fileData will now be an nFiles-by-2 matrix of numeric values. You can sort these values using the function SORTROWS. The following code will sort first by the integer following the word data and next by the date number:
[fileData,index] = sortrows(fileData,1:2); %# Sort numeric values
fileNames = fileNames(index); %# Apply sort to file names
Concatenating the files...
The fileNames variable now contains a cell array of all the files in the given directory that match the desired file name format, sorted first by the integer following the word data and then by the date. If you now want to concatenate all of these files into one large file, you could try using the SYSTEM function to call a system command to do this for you. If you are using a Windows machine, you can do something like what I describe in this answer to another SO question where I show how you can use the DOS for command to concatenate text files. You can try something like the following:
inFiles = strcat({'"'},fileNames,{'", '}); %# Add quotes, commas, and spaces
inFiles = [inFiles{:}]; %# Create a single string
inFiles = inFiles(1:end-2); %# Remove last comma and space
outFile = 'total_data.txt'; %# Output file name
system(['for %f in (' inFiles ') do type "%f" >> "' outFile '"']);
This should create a single file total_data.txt containing all of the data from the individual files concatenated in the order that their names appear in the variable fileNames. Keep in mind that each file will probably have to end with a new line character to get things to concatenate correctly.
An alternative to what #gnovice suggested is to loop over the file names and use sscanf() to recover the different sections in the filenames you are interested in:
n = sscanf(filename, 'data%d_%d_%d_%d_%d.%d')
n(1) %# data number
n(2) %# the year
...
Example:
files = dir('data*'); %# list all entries beginning with 'data'
parts = zeros(length(files), 6); %# read all the 6 parts into this matrix
for i=1:length(files)
parts(i,:) = sscanf(files(i).name, 'data%d_%d_%d_%d_%d.%d')'; %'#transposed
end
[parts idx] = sortrows(parts, [6 1]); %# sort by one/multiple columns of choice
files = files(idx); %# apply the new order to the files struct
EDIT:
I just saw your edit about merging those files. That can be done easily from the shell. For example lets create one big file for all data from the year 2009 (assuming it makes sense to stack files on top of each other):
on Windows:
type data*_2009_* > 2009.backup
on Unix:
cat data*_2009_* > 2009.backup
In Matlab the function call
files = dir('.');
returns a structure (called files) with fields
name
date
bytes
isdir
datenum
You can use your usual Matlab techniques for manipulating files.names.