save in array vars of loaded files Matlab - matlab

I have
load t1.txt;
load t2.txt;
load t3.txt;
load t4.txt;
data=t1;
vector =[ 2 , 3 , 4 , 5 , 6 ];
for i = vector
[TempFlag, MemberInd] = ismember( i, vector );
fprintf('vector(%d) is %d\n', MemberInd, i);
scatter( data(:,1),data(:,2))
end
if I want to do the above loop with all 4 files, How would you load them in a vector or something, so with each iteration it does other data?.
So I want to avoid:
data = t2;
(loop)
data = t3;
(loop)
etc...

You've set data=1, yet used it like a matrix in this line :scatter( data(:,1),data(:,2))... that should've given you a Index exceeds matrix dimensions error.
Assuming that was a typo, and that you just want to do it for different values of data, use nested loops.
data=[1,2,3,4];
vector=[2,3,4,5,6];
for i=data
for j=vector
<do stuff here>
end
end
EDIT
If your files are named t-{a,e,i,o,u} and the data variables are named the same, then you can try the following:
fileName={'ta','te','ti','to','tu'};
for i=1:length(fileName)
dummy=load(sprintf('%s.txt',fileName{i}));
eval(sprintf('data=dummy.%s',fileName{i}));
<other stuff here>
end

Related

Merge all data from xyz files in Matlab

I have a set of 501 XYZ files which I load in as
for k = 1:501
% AIS SEC data
AIS_SEC{k} = importdata(['AIS_SEC(' num2str(k) ').xyz']);
end
This generates an 1x501 cell array in which all data are stored (I uploaded this file as in attachment at https://nl.mathworks.com/matlabcentral/answers/486579-how-to-merge-multiple-xyz-files-into-1-large-array). How can I merge all these data to have 1 large XYZ file? The ultimate goal is the have a nx3 array where all of the data from the seperate xyz files are merged in to 1.
For example, to concentrate X data, I tried:
for k = 1:501
my_field = sprintf('X%d', k);
variable.(my_field) = ([AIS_SEC{1,k}.data(:,1)]);
end
BUT: Dot indexing is not supported for variables of this type.
Thanks!
There are several wrong things with your code:
First thing, the error Struct contents reference from a non-struct array object. shows up first at index k=33 because the structure imported has no data field (the import was probably empty or failed).
Checking for the presence of the field let the code run through to completion. You'll then notice that you have 8 rows which are empty.
load('AIS_SEC.mat')
n=numel(AIS_SEC) ;
EmptyRows = false(n,1) ;
for k = 1:n
my_field = sprintf('X%03d', k);
if isfield( AIS_SEC{1,k} , 'data')
variable.(my_field) = AIS_SEC{1,k}.data;
else
variable.(my_field) = [] ;
EmptyRows(k) = true ;
end
end
fprintf('Number of empty rows encountered: %u\n',sum(EmptyRows))
I took the liberty to also remove unnecessary parenthesis, added an empty row index counter, and adjusted the sprintf output format so all your field will have the same length (even the first field will have the leading zeros. 'X001' to 'X500' instead of 'X1' to 'X500').
Also, this was only retrieving the first column out of each structure, so I modified it to retrieve the 3 x,y,z columns. If you really wanted only the first column, just replace variable.(my_field) = AIS_SEC{1,k}.data by variable.(my_field) = AIS_SEC{1,k}.data(:,1).
Now this gives you a long structure with 500 fields (each representing one imported variable). Your question is not clear enough on that point but if you want to have a single array where all the values are merged, then you have 2 options:
1) Directly after the code above, convert your structure to a merged array:
vararray = cell2mat(struct2cell(variable)) ;
2) If the steps above (the final variable structure) is not something you need to keep, then you can avoid it in the first place:
load('AIS_SEC.mat')
n = numel(AIS_SEC) ; % number of field to import
% first pass we count how many data point (if any) each structure has
EmptyRows = false(n,1) ;
npts = zeros(n,1) ;
for k = 1:n
if isfield( AIS_SEC{1,k} , 'data')
npts(k) = size( AIS_SEC{1,k}.data , 1 ) ;
else
EmptyRows(k) = true ;
end
end
% fprintf('Number of empty rows encountered: %u\n',sum(EmptyRows))
% The above allows us to preallocate the output matrix at the right size
cumpts = cumsum(npts) ;
totalNumberOfPoints = cumpts(end) ;
vararray = zeros(totalNumberOfPoints,3) ;
% first field to import
vararray( 1:cumpts(1) , : ) = AIS_SEC{1,1}.data ;
% now all the remaining ones
for k = 2:n
idx = (cumpts(k-1)+1):cumpts(k) ;
if ~isempty(idx)
vararray(idx,:) = AIS_SEC{1,k}.data ;
end
end
In this version there are 2 passes of the loop accross the structure. Counter intuitively this is done for better performances. The first pass is only to count the number of data points in each structure (and also to flag the empty ones). Thanks to the number returned by the first pass, we can preallocate the output matrix before the second pass and assign each structure data to the merged array in the right place without having to resize the output array at each iteration.

Create a 2 column matrix with 2 different format types

very very new to Matlab and I'm having trouble reading a binary file into a matrix. The problem is I am trying to write the binary file into a two column matrix (which has 100000's of rows) where each column is a different format type.
I want column 1 to be in 'int8' format and column 2 to be a 'float'
This is my attempt so far:
FileID= fopen ('MyBinaryFile.example');
[A,count] = fread(FileID,[nrows, 2],['int8','float'])
This is not working because I get the error message 'Error using fread' 'Invalid Precision'
I will then go on to plot once I have successfully done this.
Probably a very easy solution to someone with matlab experience but I haven't been successful at finding a solution on the internet.
Thanks in advance to anyone who can help.
You should be aware that Matlab cannot hold different data type in a matrix (it can do so in a cell array but this is another topic). So there is no point trying to read your mixed type file in one go in one single matrix ... it is not possible.
Unless you want a cell array, you will have to use 2 different variables for your 2 columns of different type. Once this is established, there are many ways to read such a file.
For the purpose of the example, I had to create a binary file as you described. This is done this way:
%% // write example file
A = int8(-5:5) ; %// a few "int8" data
B = single(linspace(-3,1,11)) ; %// a few "float" (=single) data
fileID = fopen('testmixeddata.bin','w');
for il=1:11
fwrite(fileID,A(il),'int8');
fwrite(fileID,B(il),'single');
end
fclose(fileID);
This create a 2 column binary file, with first column: 11 values of type int8 going from -5 to +5, and second column: 11 values of type float going from -3 to 1.
In each of the solution below, the first column will be read in a variable called C, and the second column in a variable called D.
1) Read all data in one go - convert to proper type after
%% // Read all data in one go - convert to proper type after
fileID = fopen('testmixeddata.bin');
R = fread(fileID,'uint8=>uint8') ; %// read all values, most basic data type (unsigned 8 bit integer)
fclose(fileID);
R = reshape( R , 5 , [] ) ; %// reshape data into a matrix (5 is because 1+4byte=5 byte per column)
temp = R(1,:) ; %// extract data for first column into temporary variable (OPTIONAL)
C = typecast( temp , 'int8' ) ; %// convert into "int8"
temp = R(2:end,:) ; %// extract data for second column
D = typecast( temp(:) , 'single' ) ; %// convert into "single/float"
This is my favourite method. Specially for speed because it minimizes the read/seek operations on disk, and most post calculations are done in memory (much much faster than disk operations).
Note that the temporary variable I used was only for clarity/verbose, you can avoid it altogether if you get your indexing into the raw data right.
The key thing to understand is the use of the typecast function. And the good news is it got even faster since 2014b.
2) Read column by column (using "skipvalue") - 2 pass approach
%% // Read column by column (using "skipvalue") - 2 pass approach
col1size = 1 ; %// size of data in column 1 (in [byte])
col2size = 4 ; %// size of data in column 2 (in [byte])
fileID = fopen('testmixeddata.bin');
C = fread(fileID,'int8=>int8',col2size) ; %// read all "int8" values, skipping all "float"
fseek(fileID,col1size,'bof') ; %// rewind to beginning of column 2 at the top of the file
D = fread(fileID,'single=>single',col1size) ; %// read all "float" values, skipping all "int8"
fclose(fileID);
That works too. It works fine ... but probably much slower than above. Although it may be clearer code to read for someone else ... I find that ugly (and yet I've used this way for several years until I got to use the method above).
3) Read element by element
%% // Read element by element (slow - not recommended)
fileID = fopen('testmixeddata.bin');
C=[];D=[];
while ~feof(fileID)
try
C(end+1) = fread(fileID,1,'int8=>int8') ;
D(end+1) = fread(fileID,1,'single=>single') ;
catch
disp('reached End Of File')
end
end
fclose(fileID);
Talking about ugly code ... that does work too, and if you were writing C code it would be more than ok. But in Matlab ... please avoid ! (well, your choice ultimately)
Merging in one variable
If really you want all of that in one single variable, it could be a structure or a cell array. For a cell array (to keep matrix indexing style), simply use:
%% // Merge into one "cell array"
Data = { C , D } ;
Data =
[11x1 int8] [11x1 single]

Dividing a DataArray and putting names to each Matlab

I have a data array with dimensions 1 x 95125. I want to extract data from it and then give each a name. For example
Station00001=[R{:,1:13}]
Station00002=[R{:,15:27}]
.....
Station06518
The question is, is it possible to create a vector with all the wanted names and then open each data from the data array as above but with all the files with a for loop to its corresponding file
This is what I did but its not working
for i= 1:(length(R)/14)
k=0:((length(R)/14)-1)
A(i)=1+14.*k;
B(i)=A+12;
Stations (i)= [R{:,A(i):B(i)}];
end
Your loop is fine; not sure why you would want to store the A and B indices in an array, though.
numStations = floor(length(R)/14); %# careful: the number of columns in R is not a multiple of 14
Stations = cell(1,numStations);
for i= 1:numStations
fromColumn = (i-1)*14+1;
toColumn = i*14-1;
Stations{i}= [R{:,fromColumn:toColumn}];
end
To access the data from Station 25, use Stations{25}

Storing each iteration of a loop in Matlab

I have a 2d matrix (A=80,42), I am trying to split it into (80,1) 42 times and save it with a different name. i.e.
M_n1, M_n2, M_n3, … etc (representing the number of column)
I tried
for i= 1:42
M_n(i)=A(:,i)
end
it didn't work
How can I do that without overwrite the result and save each iteration in a file (.txt) ?
You can use eval
for ii = 1:size(A,2)
eval( sprintf( 'M_n%d = A(:,%d);', ii, ii ) );
% now you have M_n? var for you to process
end
However, the use of eval is not recommanded, you might be better off using cell array
M_n = mat2cell( A, [size(A,1)], ones( 1, size(A,2) ) );
Now you have M_n a cell array with 42 cells one for each column of A.
You can access the ii-th column by M_n{ii}
Generally, doing if you consider doing this kind of things: don't.
It does not scale up well, and having them in one array is usually far more convenient.
As long as the results have the same shape, you can use a standard array, if not you can put each result in a cell array eg. :
results = cell(nTests,1)
result{1} = runTest(inputs{1})
or even
results = cellfun(#runTest,inputs,'UniformOutput',false); % where inputs is a cell array
And so on.
If you do want to write the numbers to a file at each iteration, you could do it without the names with csvwrite or the like (since you're only talking about 80 numbers a time).
Another option is using matfile, which lets you write directly to a variable in a .mat file. Consult help matfile for the specifics.

automating loading of multiple *.mat files & matrix resize

I have a ton of data that needs to be processed from lab work. I have a ton of .mat files that contain a signal matrix of dimensions 7 x w. I need to resize the matrix to 7 x N and w is larger and smaller than N to make the rest of the analysis easier (don't care about data past N). I have the psuedocode of how I want this to work but don’t know how to implement it. Any help would be great thanks!
Folder structure of all my data:
Main folder
Alpha 1
1111.mat
1321.mat
Alpha 2
1010.mat
1234.mat
1109.mat
933.mat
Alpha 3
1223.mat
etc.
Psudeocode:
Master_matrix = []
For all n *.mat
Load n'th *.mat from alpha 1
If w > N
Resize matrix down to N
Else
Zero pad to N
End if
Master_matrix = master_matrix .+ new resized matrix
End for
rest of my code...
First you need to generate the file list. I have my own function for that, but there is, for example, GETFILELIST or the excellent interactive UIPICKFILES to generate the list of files.
Once you have the file list (I'll assume it's a cell array containing the filenames), you can do the following:
nFiles = length(fileList);
Master_matrix = zeros(7,N);
for iFile = 1:nFiles
%# if all files contain a variable of the same name,
%# you can simplify the loading by not assigning an output
%# in the load command, and call the file by
%# its variable name (i.e. replace 'loadedData')
tmp = load(fileList{iFile});
fn = fieldnames(tmp);
loadedData = tmp.(fn{1});
%# find size
w = size(loadedData,2);
if w>=N
Master_matrix = Master_matrix + loadedData(:,1:N);
else
%# only adding to the first few columns is the same as zero-padding
Master_matrix(:,1:w) = Master_matrix(:,1:w) = loadedData;
end
end
Note: In case you don't actually want to add up the data, but simply store it in the master array, you can make Master_matrix into a 7-by-N-by-nFiles array, where the nth plane of Master_matrix is the content of the nth file. In this case, you'd initialize Master_matrix as
Master_matrix = zeros(7,N,nFiles);
and you'd write the if-clause as
if w>=N
Master_matrix(:,:,iFile) = Master_matrix(:,:,iFile) + loadedData(:,1:N);
else
%# only adding to the first few columns is the same as zero-padding
Master_matrix(:,1:w,iFile) = Master_matrix(:,1:w,iFile) = loadedData;
end
Also note that you might want to initialize Master_matrix as NaN instead of zeros, so that the zeros don't affect subsequent statistics (if that's what you want to do with the data).