How can I concatenate the arrays in loop ? Matlab - arrays

There is a loop;
for i = 1:n
X_rotate = X.*cos(i*increment) - Y.*sin(i*increment);
X_rotateh = X_rotate./cos(deg2rad(helix_angle));
Y_rotate = X.*sin(i*increment) + Y.*cos(i*increment);
Helix = [X_rotateh(1:K1) ; Y_rotate(1:K1)];
fileID = fopen('helix_values.txt', 'w');
fprintf(fileID,'%f %f\n ', Helix);
fclose(fileID);
end
X and Y are row vectors and their size depends on inputs. By the way, the iteration number n and the size of X and Y can be different. As I said, they depend on inputs.
When open the text file, there just exists the values of last iteration for X_rotateh and Y_rotate. I need to collect the values of X_rotateh and Y_rotate from first value to K1 th value of both for every iteration. I have tried to use cat command. It did not give what I want. On the other hand, I usually meet problems which are about length or size of arrays.
Those values should be in order in text file like;
%for first iteration;
X_rotateh(1) Y_rotate(1)
X_rotateh(2) Y_rotate(2)
.
.
X_rotateh(K1) Y_rotate(K1)
%for second iteration;
X_rotateh(1) Y_rotate(1)
X_rotateh(2) Y_rotate(2)
.
.
X_rotateh(K1) Y_rotate(K1)
%so on..
What may I do ?
Thanks in advance.

As you said, the text file has results from the last iteration. It's probably because you are opening the text file with 'w' permission. Which writes the new content but also erases the previously stored content in the file. Try using 'a' permission. This will append new content without erasing previous content.
fileID = fopen('helix_values.txt', 'a');
You can also find more details with help fopen command in MATLAB.
Let me know if this solves the problem.

Related

How to save dynamic variable from workspace in a separate file in matlab?

I'm working on a problem where I have an array A of 100 elements.
All these 100 elements are changing with time.
So in my workspace, I only get the final values of all these elements after the entire time cycle has run.
I'm trying to save the values with time in a separate file (.txt or .mat) so that I can access that file in order to check how the variable varies with time.
I'm trying the following command:
save('file.mat','A','-append');
But this command overwrites the existing values in my file.
Kindly suggest me a way to save these values without overwriting them and also guide me how to access them in MATLAB.
You can also change the output filename to be unique for each iteration:
for iter=1:n
A = rand(10);
save(sprintf('file%d.mat',iter), 'A');
end
That way each iteration creates one file.
The reason that saving to a file (even using the -append) flag didn't work is because the variable A already exists in the file and will be over-written each time through the loop. You would need to create a new file or new variable name every time through the loop in order for this to not happen.
Saving the results in a file is probably not the best way to store the time-varying values of A. You would be better off using a cell array to store all intermediate values of A.
A_over_time = cell();
for k = 1:n
%// Get A somehow
A_over_time{k} = A;
end
Depending on what A is, you could also store the values of A in a numeric array or matrix.
%// Using an array
A_over_time = zeros(N, 1);
for k = 1:N
A_over_time(k) = A;
end
%// Using a matrix
A_over_time = zeros(N, numel(A));
for k = 1:N
A_over_time(k,:) = A;
end

append char array to cell array in matlab

I am a Matlab beginner, as will soon be very obvious. I am trying to assemble an cell array that has a single column of filenames.
I have multiple sessions. Each session should have 56 filenames (but some could be short or long, so I'd honestly prefer a solution that wouldn't break on encountering a short session). I need to loop over sessions and append the names in each subsequent session to my cell array, so that after two sessions the dimensions are 112, 1.
In other words, I'd like an array that went:
P =
/data/session1/dvol1.img
/data/session1/dvol2.img
...
/data/session1/dvol56.img
/data/session2/dvol1.img
/data/session2/dvol2.img
...
/data/session2/dvol56.img
and so on if there are more than two sessions.
The function I have that finds the filenames in the session is spm_select. It returns a char array of all the files in a directory that match a regular expression, in this case, 56 files for each session directory.
(I recognize my question is very similar to the question here: Using loops to get multiple values into a cell but I couldn't figure out an answer to my question since that person is only trying to append a single value at a time.)
I have tried a lot of things that haven't worked.
This:
data_path = '/foo/bar/';
subjects = {'test1'};
sessions = {'session1' 'session2' };
for i=1:numel(subjects)
clear P
P=cell(56*numel(sessions),1);
for j=1:numel(sessions)
P{(j-1)*56+1} = spm_select('FPList', fullfile(data_path,subjects{i}, sessions{j}), '^d.*\.img$');
end
end
generated a cell array that was 112x1, but had a first element that was 56x57 char array, that is, the filenames of all files in my first session directory, and none of them from the second.
I'm not sure how useful it would be to recapitulate every wrong-headed thing I've done, so I won't.
Thanks in advance for your help.
Editing to include sample output from spm_select by request:
>> output = spm_select('FPList', fullfile(data_path,subjects{i}, sessions{j}), '^d.*\.img$')
output =
/home/katie/Desktop/sample/test1/run_1L3/draghf000001.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000035.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000069.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000103.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000137.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000171.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000205.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000239.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000273.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000307.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000341.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000375.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000409.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000443.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000477.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000511.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000545.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000579.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000613.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000647.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000681.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000715.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000749.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000783.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000817.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000851.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000885.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000919.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000953.img
/home/katie/Desktop/sample/test1/run_1L3/draghf000987.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001021.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001055.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001089.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001123.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001157.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001191.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001225.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001259.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001293.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001327.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001361.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001395.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001429.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001463.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001497.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001531.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001565.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001599.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001633.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001667.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001701.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001735.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001769.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001803.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001837.img
/home/katie/Desktop/sample/test1/run_1L3/draghf001871.img
>> class(output)
ans =
char
>> size(output)
ans =
56 57
>>
Edit: Ok, problem solved. Here is the code I eventually used:
data_path = '/foo/bar';
subjects = {'test1'};
sessions = {'session1' 'session2' };
output={};
for i=1:numel(subjects)
for j=1:numel(sessions)
files=spm_select('FPList', fullfile(data_path,subjects{i},sessions{j}), '^d.*\.img$')
f_c=cellstr(files);
output=vertcat(output,f_c);
end
end
I think the answer to how "do you get a char array to append to a column cell array vertically" is convert it to a cell array and use vertcat.
You can try this code:
function output=file_list(path)
output={};
subjects=dir(path);
for a=3:length(subjects)
sessions=dir(fullfile(path,subjects(a).name));
for b=3:length(sessions)
files=dir(fullfile(path,subjects(a).name,'/',sessions(b).name,'/*.img'));
f_c=struct2cell(files);
f=f_c(1,:)';
output=vertcat(output,fullfile(path,subjects(a).name,'/',sessions(b).name,'/',f));
end
end
One drawback of this code is that the size of output grows inside the loop. Here is an example:
path='/home/naveen/Desktop/example/'; % path is the main directory in which the data of
% subjects is stored in sub directories.
output=file_list(path)
The output is:
output =
'/home/naveen/Desktop/example/subject_1/session_1/lipo2.png'
'/home/naveen/Desktop/example/subject_1/session_1/lipo_6.png'
'/home/naveen/Desktop/example/subject_1/session_1/lps_4.png'
'/home/naveen/Desktop/example/subject_1/session_2/ltx_2.png'
'/home/naveen/Desktop/example/subject_1/session_2/ltx_2_1.png'
'/home/naveen/Desktop/example/subject_1/session_2/ltx_2_3.png'
'/home/naveen/Desktop/example/subject_1/session_2/ltx_4.png'
'/home/naveen/Desktop/example/subject_1/session_2/ltx_6.png'
'/home/naveen/Desktop/example/subject_2/session_1/lipo2.png'
'/home/naveen/Desktop/example/subject_2/session_1/lipo_6.png'
'/home/naveen/Desktop/example/subject_2/session_1/lps_4.png'
'/home/naveen/Desktop/example/subject_2/session_2/ltx_2.png'
'/home/naveen/Desktop/example/subject_2/session_2/ltx_2_1.png'
'/home/naveen/Desktop/example/subject_2/session_2/ltx_2_3.png'
'/home/naveen/Desktop/example/subject_2/session_2/ltx_4.png'
'/home/naveen/Desktop/example/subject_2/session_2/ltx_6.png'
Hope this works for you. Please note that in the inner most for loop you have to change the file extension while using for your purpose.

Best way to compare data from file to data in array in Matlab

I am having a bit of trouble with a specific file i/o in matlab, I am fairly new to it still so some things are still a bit of a mystery to me. The input file is structured as so:
File Name: Processed_kplr003942670-2010174085026_llc.fits.txt
File contents- 6 Header Lines then:
1, 2, 3
1, 2, 3
basically a matrix of about [1443,3] with varying values
now here is the matrix that I'm comparing it to:
[(0123456, 1, 2, 3), (0123456, 2, 3, 4), (etc..)]
Now here is my problem, first I need to know how to properly do the file input in a way which can let me compare the ID number (0123456) that is in the filename with the ID value that is in the matrix, so that I can compare the other columns of both. I do not know how to achieve this in matlab. Furthermore, I need to be able to loop over every point in the the matrix that matches up to the specific file, for example:
If I have 15 files ranging from 'Processed_0123456_1' to 'Processed_0123456_15' then I want to be able to read in the values contained in 'Processed_0123456_1'and compare them to ANY row in the matrix that corresponds to that ID (0123456). I don't know if maybe accumaray can be used for this, but as I said I'm not sure.
So the code must:
-Read in file
-Compare file to any point in the matrix with corresponding ID
-Do operations
-Loop over until full list of files in the directory are read in and processed, and output a matrix with the results.
Thanks for any help.
EDIT: Exact File Sample--
Kepler I.D.-----Channel
[1161345]--------[84]
-TTYPE1--------TTYPE8------------TTYPE4
['TIME']---['PDCSAP_FLUX']---['SAP_FLUX']
['BJD - 2454833']--['e-/s']--------['e-/s']
CROWDSAP --- 0.9791
630.195880143,277165.0,268233.0
630.216312946,277214.0,268270.0
630.23674585,277239.0,268293.0
630.257178554,277296.0,268355.0
630.277611357,277294.0,268364.0
630.29804426,277365.0,268441.0
630.318476962,277337.0,268419.0
630.338909764,277403.0,268481.0
630.359342667,277389.0,268463.0
630.379775369,277441.0,268508.0
630.40020817,277545.0,268604.0
There are more entries than what was just posted but they go for about 1000 lines so it is impractical to post that all here.
To get the file ID, use regular expressions, e.g.:
filename = 'Processed_0123456_1';
file_id_str = regexprep(filename, 'Processed_(\d+)_\d+', '$1');
file_num_str = regexprep(filename, 'Processed_\d+_(\d+)', '$1')
To read in the file contents, assuming that it's all comma-separated values without a header, use textscan, e.g.,
fid = fopen(filename)
C = textscan(fid, '%f,%f,%f') % Use as many %f specifiers as you have entries per line in the file
textscan also works on strings. So, for example, if your file contents was:
filestr = sprintf('1, 2, 3\n1, 3, 3')
Then running textscan on filestr works like this:
C = textscan(filestr, '%f,%f,%f')
C =
[2x1 int32] [2x1 int32] [2x1 int32]
You can convert that to a matrix using cell2mat:
cell2mat(C)
ans =
1 2 3
1 3 3
You could then repeat this procedure for all files with the same ID and concatenate them into a single matrix, e.g.,
C_full = [];
for (all files with the same ID)
C = do_all_the_above_stuff;
C_full = [C_full; C];
end
Then you can look for what you want in C_full.
Update based on updated OP Dec 12, 2013
Here's code to read the values from a single file. Wrap this all in the the loop that I mentioned above to loop over all your files and read them all into a single matrix.
fid = fopen('/path/to/file');
% Skip over 12 header lines
for kk = 1:12
fgetl(fid);
end
% Read in values to a matrix
C = textscan(fid, '%f,%f,%f');
C = cell2mat(C);
I think your requirements are too complicated to write the whole script here. Nonetheless, I will try to give some pointers to help. Disclaimer: None of this is tested, just my best guess. Please expect syntax errors, etc. I hope you can figure them out :-)
1) You can use the textscan function with the delimiter option to get data from the lines of your file. Since your format varies as it does, we will probably want to use...
2) ... fgetl to read the first two lines into strings and process them separately using texstscan. Such an operation might look like:
fid = fopen('file.txt','w');
tline1 = fgetl(fid);
tline2 = fgetl(fid);
fclose(fid);
C1 = textscan(tline1,'%s %d %s','delimiter','_'); %C1{2} will be the integer we want
C2 = textscan(tline2,'%s %s'),'delimiter,':'); %C2{2} will be the values we want, but they're still a string so...
mat = str2num(C2{2});
3) Then, for the rest of the lines, we can use something like dlmread:
mat2 = dlmread('file.txt',',',2,0);
The 2,0 specifies the offset in 0-based rows,columns from the start of the file. You may need to look at something like vertcat to stitch mat and mat2 together.
4) The list of files in the directory can be found with the dir command. The filename is an attribute of the structure that's returned:
dirlist = dir;
for i = 1:length(dirlist)
filename = dirlist(i).name
%process your files
end
You can also pass matching strings to dir, like so:
dirlist = dir('*.txt');
which will find all of the files with extension .txt.
5) You can very easily loop through the comparison matrix:
sze = size(comparisonmatrix);
for i = 1:sze(1)
%compare comparisonmatrix(i,1) to C1{2}
%Perform whatever operations you need
end
Hope that helps!

Matlab - Importing a .dat file into an array

I'm still fairly new to Matlab but for some reason the documentation hasn't been all that helpful with this.
I've got a .dat file that I want to turn into a _ row by 6 column array (the number of rows changes depending on the program that's generating the .dat file). What I need to do is get the dimensions of the image this array will be used to make from the 1st row 2nd column (x dimension) and 1st row 4th column (y dimension). When using the Import Data tool in Matlab, this works properly:
However I need the program to do it automatically. If the first line wasn't there, I'm pretty sure I could just use fscanf to put the data in the array, but the image dimensions are necessary.
Any idea what I need to use instead?
You may use textscan. The first call to this function will handle the first line (i.e. get the dimension of your file) and the second call the remaining of your file. The second call uses repmat to declare the format spec: %f, meaning double, repeated nb_col times. The option CollectOutput will concatenate all the columns in a single array. Note that textscan can read the entire file without specifying the number of rows.
The code would be
fileID = fopen('youfile.dat'); %declare a file id
C1 = textscan(fileID,'%s%f%s%f'); %read the first line
nb_col = C1{4}; %get the number of columns (could be set by user too)
%read the remaining of the file
C2 = textscan(fileID, repmat('%f',1,nb_col), 'CollectOutput',1);
fclose(fileID); %close the connection
In the case where the the number of columns is fixed, you can simply do
fileID = fopen('youfile.dat');
C1 = textscan(fileID,'%s%f%s%f'); %read the first line
im_x = C1{2}; %get the x dimension
im_y = C1{4}; %get the x dimension
C2 = textscan(fileID,'%f%f%f%f%f%f%*[^\n]', 'CollectOutput',1);
fclose(fileID);
The format specification %*[^\n] skips the remaining of a line.

files comparison

I'm trying to compare 2 txt files to check files are equals otherwise, get the output and give difference (say that there are a diff line x)
I'm trying as follows:
fid1 = fopen(file_1, 'r');
fid2 = fopen(file_2, 'r');
lines1 = textscan(fid1,'%s','delimiter','\n');
lines2 = textscan(fid2,'%s','delimiter','\n');
lines1 = lines1{1};
lines2 = lines2{1};
fclose(fid1);
fclose(fid2);
tf = isequal(lines1,lines2); % this gives 0 or 1
I would like when the value is 0 (files are different) to localize the diff and give line where files are different or print content of difference.
You essentially want to compare each element of the two cell arrays you have, not the whole cell arrays. You could do that with a loop in most languages, but of course MATLAB has many ways to avoid loops. Here, it is cellfun:
cellfun(#isequal,lines1,lines2)
(I left out the part where, if the two cell arrays are of unequal size, you have to shorten the longer one.) Then, find is useful for finding the first (or all) occurrence(s) of a certain value in any vector.

Resources