concatenate on the third dimension for each subject - matlab

I have one file .mat for each condition (4) and each subject (24). So, I have in total 96 files .mat.
Example:
cond1_sbj5_ToProcess_av.mat, cond1_sbj7_ToProcess_av.mat, cond1_sbj10_ToProcess_av.mat, etc.
cond2_sbj5_ToProcess_av.mat, cond2_sbj7_ToProcess_av.mat, cond2_sbj10_ToProcess_av.mat, etc.
cond3_sbj5_ToProcess_av.mat, cond3_sbj7_ToProcess_av.mat, cond3_sbj10_ToProcess_av.mat, etc.
cond4_sbj5_ToProcess_av.mat, cond4_sbj7_ToProcess_av.mat, cond4_sbj10_ToProcess_av.mat, etc.
In each file, depending on the condition, I have a variable that is 66x3000single. AA1 for condition1, AA2 for condition2, AA3 for condition3, AA4 for condition4.
I would like to concatenate on the third dimension AA1,AA2,AA3,AA4 for each subject, in a loop.
So, for each subject I should obtain a 3D matrix/structure with 4 'sheets' as third dimension.
Any suggestion? Thanks a lot.

ok new try with all previous approaches deleted. Here you go. The problem was that cond_number was a string and using a string as an index created the 52, also the load (filename) was missing. However, I tried it with some dummy files and now it works, but only if your subject numbers are running from 1 to 24 and not like 1 5 7 9 19 .... If that is the case you need to modify the code accordingly. Good luck!
clear all
close all
origindir = 'c:\yourdirectory';
cd (origindir)
av_files = dir(fullfile('*.mat'));
mymatrix = zeros(24,66,3000,4);
for ifile = 1:size(av_files,1)
filename = av_files(ifile).name;
load(filename)
if ~isempty(str2num(filename(10:11)))
sub_number = str2num(filename(10:11));
else
sub_number = str2num(filename(10));
end
cond_number_str = filename(5);
cond_number = str2double(cond_number_str);
varname = strcat('AA',cond_number_str);
mymatrix(sub_number,:,:,cond_number)=eval(sprintf(varname));
end
for sub = 1:24
varname2 = strcat('newmat',num2str(sub));
eval([sprintf('%s = squeeze(mymatrix(%i,:,:,:));',varname2,sub)])
end

Related

Problem adding tow digits to path string to read multiple files

I want to read multiple files from a folder, the only problem in my code down is that
instead of having the full image path:
'checkboard/Gaussian_Noised/image_01.jpg'
I have the path without the zero in the last two digits
EDIT: There is space instead of zero on the first 9 Image paths.
'checkboard/Gaussian_Noised/image_ 1.jpg'
how can I fix this please
%-------------------------------------------------------
clc
clear all
close all
%------------------------------------------------------
path = 'checkboard/Gaussian_Noised/';
% Define images to process
imageFileNames = cell(1,36);
for n = 1:36
imageFileNames{n} = strcat(path,sprintf('image_%2d.jpg',n))
end
%------------------------------------------------------
In this case, it is better to use the float-format-specifier to pad zeros:
num2str(1,'%02.f')
'01'
num2str(1,'%02.d')
'1'
num2str(1,'%2.d')
'1'
num2str(1,'%d')
'1'
So in your case:
sprintf('image_%02.f.jpg',n)
general advice
As a general advice, you may want just to check the folder for all files of a certain pattern
path2dir = pwd; % path to working directory
pattern = 'image_*.jpg'
Lst = dir(fullfile(path2dir ,pattern));
for i = 1:length(Lst)
path2file = fullfile(Lst(i).folder,Lst(i).name);
% load the file and do something with it
end

retriving a text file content information in Matlab

I have a .txt file which includes 300 lines. For example the first line is:
ANSWER: correct: yes, time: 6.880674, guess: Lay, action: Lay, file: 16
or the second line is:
ANSWER: correct: no, time: 7.150422, guess: Put on top, action: Stir, file: 18
Only 'time' and 'file' values are numbers and the others are string.
I want to store the values of "correct", "time", "guess", "action" and "file" of the whole 300 lines in the different variables (like some arrays).
How can I do this in the Matlab?
Option 1:
You can use textscan with the following formatSpec:
formatSpec = 'ANSWER: correct:%s time:%f guess:%s action:%s file: %f';
data = textscan(fileID,formatSpec,'Delimiter',',');
where fileID is the file identifier obtained by fopen.
Option 2:
Another option is to use readtable, with the formatting above (directly with the file name, no fileID):
data = readtable('53485991.txt','Format',formatSpec,'Delimiter',',',...
'ReadVariableNames',false);
% the next lines are just to give the table variables some meaningful names:
varNames = strsplit(fmt,{'ANSWER',':','%s',' ','%f'});
data.Properties.VariableNames = varNames(2:end-1);
The result (ignore the values, as I messed that example a little bit while playing with it):
data =
4×5 table
correct time guess action file
_______ ______ _______________ ______ ____
'yes' 6.8888 'Lay' 'Lay' 16
'no' 7.8762 'Put on top' 'Stir' 18
'no' 7.1503 'Put on bottom' 'Stir' 3
'no' 7.151 'go' 'Stir' 270
The advantage in option 2 is that a table is a much more convenient way to hold these data than a cell array (which is the output of textscan).
Use fgetl to get a line of the file and while loop to read all of the lines.
For each line, use regexp to partition the string into cells by : and , delimiter. Then, use strip to remove leading and trailing whitespace for each cell.
Here is the solution:
f = fopen('a.txt');
aline = fgetl(f);
i = 1;
while ischar(aline)
content = strip(regexp(aline,':|,','split'));
correct{i} = content{3};
time(i) = str2double(content{5});
guess{i}= content{7};
action{i} = content{9};
file(i) = str2double(content{11});
i = i + 1;
aline = fgetl(f);
end
fclose(f);
Example:
Suppose a.txt file looks like this
ANSWER: correct: yes, time: 6.880674, guess: Lay, action: Lay, file: 16
ANSWER: correct: no, time: 7.150422, guess: Put on top, action: Stir, file: 18
After executing the script, the results are
correct =
1×2 cell array
'yes' 'no'
time =
6.8807 7.1504
guess =
1×2 cell array
'Lay' 'Put on top'
action =
1×2 cell array
'Lay' 'Stir'
file =
16 18

skip header in non-rectangular matrix

I have consecutive .dat files which I want to read and input into a single matrix by concatenating the files vertically. The code I have so far works fine for simple numeric files with only tabs as delimiter.
import=[];
data=[];
for i = 1:32
data1=[import dlmread(sprintf('%d.dat',i))];
data=vertcat(data, data1);
clear data1;
end
and I take the correct output into the data matrix. But my file format is as follows:
first second third
0 11/15 08:57:42.000 54 67 82
1 11/15 09:48:47.010 49 32 31
...
As you can see I have three delimiters (: \t /) and headers only in the last three columns which are essentially the ones I want to read, that is I want a matrix:
54 67 82
49 32 31
...
I tried specifying the delimiters into the dlmwrite and how many rows/columns to skip but an error occurs in sprintf ('delimiter = sprintf(delimiter); % Interpret \t (if necessary)'). Does anyone have any idea how to go about this?
UPDATE:
I managed to get a little further
data=[];
for i = 1:32
filename = sprintf( '%d.dat',i );
data1=importdata(filename);%creates a cell array
data2=cell2mat(data1(3:end,:));%converts it to char
%The data, without the header, start from the 3rd row.
data=vertcat(data, data2); %concatenate vertically all the files
clear data1; clear data2;
end
%the data
a1=str2num(data(1:end,20:25));%the first data column is in char 20-25
a2=str2num(data(1:end,30:35));%the second data column is in char 30-35
The thing is that the last part takes too much time, over an hour has passed until I manually stopped it. Does anyone know a simpler and faster way to do this?
I managed to solve this myself so I post it here for future reference:
for i = 1:32
filename = sprintf( '%d.dat',i );
data1 = dlmread(filename,'',2,3);%start from row 2, headercolumn 3
data=vertcat(data, data1);
clear data1;
end
Now the data matrix contains only my data columns and it runs in a few seconds.

Modify the value of a specific position in a text file in Matlab

AIR, ID
AIR.SIT
50 1 1 1 0 0 2 1
43.57 -116.24 1. 857.7
Hi, All,
I have a text file like above. Now in Matlab, I want to create 5000 text files, changing the number "2" (the specific number in the 3rd row) from 1 to 5000 in each file, while keeping other contents the same. In every loop, the changed number is the same with the loop number. And the output in every loop is saved into a new text file, with the name like AIR_LoopNumber.SIT.
I've spent some time writing on that. But it is kind of difficult for a newby. Here is what I have:
% - Read source file.
fid = fopen ('Air.SIT');
n = 1;
textline={};
while (~feof(fid))
textline(n,1)={fgetl(fid)};
end
FileName=Air;
% - Replace characters when relevant.
for i = 1 : 5000
filename = sprintf('%s_%d.SIT','filename',i);
end
Anybody can help on finishing the program?
Thanks,
James
If your file is so short you do not have to read it line by line. Just read the full thing in one variable, modify only the necessary part of it before each write, then write the full variable back in one go.
%% // read the full file as a long sequence of 'char'
fid = fopen ('Air.SIT');
fulltext = fread(fid,Inf,'char') ;
fclose(fid) ;
%% // add a few blank placeholder (3 exactly) to hold the 4 digits when we'll be counting 5000
fulltext = [fulltext(1:49) ; 32 ; 32 ; 32 ; fulltext(50:end) ] ;
idx2replace = 50:53 ; %// save the index of the characters which will be modified each loop
%% // Go for it
baseFileName = 'AIR_%d.SIT' ;
for iFile = 1:1000:5000
%// build filename
filename = sprintf(baseFileName,iFile);
%// modify the string to write
fulltext(idx2replace) = num2str(iFile,'%04d').' ; %//'
%// write the file
fidw = fopen( filename , 'w' ) ;
fwrite(fidw,fulltext) ;
fclose(fidw) ;
end
This example works with the text in your example, you may have to adjust slightly the indices of the characters to replace if your real case is different.
Also I set a step of 1000 for the loop to let you try and see if it works without writing 1000's of file. When you are satisfied with the result, remove the 1000 step in the for loop.
Edit:
The format specifier %04d I gave in the first solution insure the output will take 4 characters, and it will pad any smaller number with zero (ex: 23 => 0023). It is sometimes desirable to keep the length constant, and in your particular example it made things easier because the output string would be exactly the same length for all the files.
However it is not mandatory at all, if you do not want the loop number to be padded with zero, you can use the simple format %d. This will only use the required number of digits.
The side effect is that the output string will be of different length for different loop number, so we cannot use one string for all the iterations, we have to recreate a string at each iteration. So the simple modifications are as follow. Keep the first paragraph of the solution above as is, and replace the last 2 paragraphs with the following:
%% // prepare the block of text before and after the character to change
textBefore = fulltext(1:49) ;
textAfter = fulltext(51:end) ;
%% // Go for it
baseFileName = 'AIR_%d.SIT' ;
for iFile = 1:500:5000
%// build filename
filename = sprintf(baseFileName,iFile);
%// rebuild the string to write
fulltext = [textBefore ; num2str(iFile,'%d').' ; textAfter ]; %//'
%// write the file
fidw = fopen( filename , 'w' ) ;
fwrite(fidw,fulltext) ;
fclose(fidw) ;
end
Note:
The constant length of character for a number may not be important in the file, but it can be very useful for your file names to be named AIR_0001 ... AIR_0023 ... AIR_849 ... AIR_4357 etc ... because in a list they will appear properly ordered in any explorer windows.
If you want your files named with constant length numbers, the just use:
baseFileName = 'AIR_%04d.SIT' ;
instead of the current line.

MatLab - How to read a text file separated by ';', with different number of columns [duplicate]

This question already has answers here:
Fastest way to import CSV files in MATLAB
(4 answers)
Closed 9 years ago.
I'm trying to read a .txt file that is ';' delimited with date in the 'header' and diferent columns after the 'header'. I'm using quotes to HEADER because it's more like a parameter line.
So, the .txt is like (the other lines have the same number of columns):
15/07/2013;66;157
DDD;3;1;0;1;1;1;-0.565
DDD;8;2;0;2;1;1;-0.345
DDD;9;3;2;3;1;2;-0.643
DDD;8;1;3;5;1;3;-0.025
DDD;8;1;0;9;1;4;-0.411
DDD;15;1;5;4;1;5;-0.09
DDD;12;1;0;5;1;6;-0.445
DDD;13;1;0;7;1;7;-0.064
I want to read and create a matrix, that contains each data in one cell, like:
matrix =
[15/07/2013 66 157
DDD 3 1 0 1 1 1 -0,565
DDD 8 2 0 2 1 1 -0,345
DDD 9 3 2 3 1 2 -0,643
...]
I've tried textscan, cvsread, textread and nothing works!
Thanks in advance!
Edit: Actually, I found a WAY FASTER code to do this!
From my past experience, MATLAB does not like strings and numbers to be in the same matrix, so you would be forced to use a cell.
You can do this relatively easily with some simple paring.
fid = fopen('temp.txt','r'); %# open file for reading
count = 1;
content = {};
while ~feof(fid)
line = strtrim(fgets(fid)); %# read line by line
parts = regexp(line,';','split');
for i = 1:numel(parts)
temp = regexp(parts{i},'-?[0-9]*\.?[0-9]*(i|j)?','match');
if numel(temp) >= 1 && strcmpi(temp{1},parts{i})
parts{i} = str2double(parts{i}) ;
end
end
content{count} = parts;
count = count + 1;
end
fclose(fid);
numRows = size(content,2)-1;
whole = cell(numRows,8);
for i = 1:numRows
for j = 1:8
whole{i,j} = content{i+1}{j};
end
end
content = {content{1},whole};
UPDATE
I added some stuff to put everything into a single cell array, all of the data outside of the header. I do not know if you wand the header to also be in that 8 column array, but if you do here is some code to do that
numRows = size(content,2);
whole = cell(numRows,8);
for i = 1:numRows
for j = 1:min([size(content{i},2),8])
whole{i,j} = content{i}{j};
end
end
whole