I am currently working with MDF file(.mf4) in MATLAB and I don't want to see the ChannelNumsamples that contain no values or lets say zero values so how to do that? I have tried with this code. but it is not helping me to extract nonzeroes elements.
cc = table2array(dd(1,:))
if table2array(A(x,"ChannelGroupNumSamples")) >= 0
disp('YES');
A(x,3)
size(cc);
else disp('nodata')
numel(cc)
Elements = sum(cc ~= 0)
elementscount = nonzeros(Elements)
end
To open an MDF file and read the data from it, but remove channel groups that don't contain any samples, you can do something like
m = mdf('myMDFfile.mf4');
mData = m.read;
for group = 1:numel(m.ChannelGroup)
if m.ChannelGroup(group).NumSamples == 0
mData(group) = [];
end
end
Now mData is a cell array of timetables containing only the data from the channel groups that had one or more samples.
Related
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.
I have the following code to load a single matrix file in matlab
filename='1';
filetype='.txt';
filepath='D:\20170913\';
fidi = fopen(strcat(filepath,filename,filetype));
Datac = textscan(fidi, repmat('%f', 1, 640), 'HeaderLines',1,
'CollectOutput',1);
f1 = Datac{1};
sum(sum(f1))
how can I load many files, say 1-100.
Thanks in advance.
Just include everything in a for loop that loops from 1 up to N_files, which is the number of files that you have. I used the function num2str() to convert the index i to a string. I also included the matrix sum in an array file_sums and a loaded_matrices cell array that stores all the loaded matrices. If all the loaded matrices have a known and same dimensions, you could use a 2D array (ex. loaded_matrices = zeros(N_rows, N_columns, N_files); and then load the data as loaded_matrices(:,:,i) = Datac{1};).
% N_files - the number of files that you have
N_files = 100;
file_sums = zeros(1,N_files);
loaded_matrices = cell(1,N_files);
for i=1:1:N_files
filename=num2str(i);
filetype='.txt';
filepath='';
fidi = fopen(strcat(filepath,filename,filetype));
Datac = textscan(fidi, repmat('%f', 1, 640), 'HeaderLines',1,...
'CollectOutput',1);
loaded_matrices{i} = Datac{1};
file_sums(i) = sum(sum(loaded_matrices{i}));
end
I'm planning to transfer only a few feature descriptors which have been classified using SVM. I tried to put the selected descriptors in a matrix but I can't match them properly. Here's the code that I made in order to transfer the selected descriptors to another variable.
[nrows, ncolumns] = size(fdImage);
SVMResultFace = svmclassify(SVMStructFace, fdImage);
ClassifiedFace = [];
for row = 1:nrows
if SVMResultFace(row,1) == 1
ClassifiedFace = [ClassifiedFace; fdImage(row,:)];
end
end
is there a more proper way to do this? Thanks!
The easiest way to eliminate those rows from fdImage is just to use logical indexing:
SVMResultFace = svmclassify(SVMStructFace, fdImage);
include_row = SVMResultFace(:,1) == 1;
ClassifiedFace = fdImage(include_row,:);
I'm working to get a 1st level analysis completed on some fMRI data, and as it's my first time using SPM in this way, it seems as though there is no end to my frustrations. SPM includes these specific instructions:
"This *.mat file must include the following cell arrays (each 1 x n): names, onsets, and durations. eg. names=cell(1,5), onsets=cell(1,5), durations=cell(1,5), then names{2}="Second condition", onsets{2}=[3,5,19,22],durations{2}=[0,0,0,0], contain the required details of the second condition."
The code I'm using grabs the data I need from the various excel files the behavioral data is stored in, and adds them to these cell arrays.
sessionFiles = dir('*.xlsx');
allNames = {sessionFiles.name}';
conditions = 36;
% go through excel files to grab relevant column information for SPM
for i=1:length(sessionFiles)
[~,fileName,~] = fileparts(allNames{i});
% initialize cells SPM needs
names = cell(1,conditions);
onsets = cell(1,conditions);
durations = {1.75};
durations = repmat(durations,1,conditions);
% read in excel file
[num,~,~] = xlsread(sessionFiles(i).name);
trialType = num(:,6);
% grab condition information from columns: seconds=9, name=6
for j=1:conditions
index = find(trialType==j);
trialOnsets = cell(1,length(index));
names{1,j} = j;
for k=1:length(index)
trialOnsets{1,k}=double(num(index(k),9));
end
onsets{1,j} = trialOnsets;
end
% save new data for SPM
save(fileName,'names','onsets','durations');
clear names onsets durations fileName num raw text
end
I found an example which shows each cell should look like this:
I just can't figure out how to grab the numbers automatically and put them in cells like that.
I know this isn't the SPM forums, but I've seen a few questions posted and I thought I would try my luck.
With the line trialOnsets = cell(1,length(index));, trialOnsets is specified as a cell array of size 1xlength(index). Then, trialOnsets is assigned to onsets{1,j}. With this workflow, each cell of onsets will be of size 1xlength(index).
Instead, each cell of onsets should be of size 1x1 and each 1x1 cell in onsets should have a matrix of size 1xlength(index). To do this, do the following.
Specify trialOnsets as a matrix, instead of as a cell array. To do this, replace trialOnsets = cell(1,length(index)); with trialOnsets = zeros(1,length(index));.
Assign the values from num to trialOnsets, which is now a matrix (previously was a cell array). To do this, replace trialOnsets{1,k}=double(num(index(k),9)); with trialOnsets(1,k)=double(num(index(k),9));.
The edited code should be as follows:
sessionFiles = dir('*.xlsx');
allNames = {sessionFiles.name}';
conditions = 36;
% go through excel files to grab relevant column information for SPM
for i=1:length(sessionFiles)
[~,fileName,~] = fileparts(allNames{i});
% initialize cells SPM needs
names = cell(1,conditions);
onsets = cell(1,conditions);
durations = {1.75};
durations = repmat(durations,1,conditions);
% read in excel file
[num,~,~] = xlsread(sessionFiles(i).name);
trialType = num(:,6);
% grab condition information from columns: seconds=9, name=6
for j=1:conditions
index = find(trialType==j);
trialOnsets = zeros(1,length(index));
names{1,j} = j;
for k=1:length(index)
trialOnsets(1,k)=double(num(index(k),9));
end
onsets{1,j} = trialOnsets;
end
% save new data for SPM
save(fileName,'names','onsets','durations');
clear names onsets durations fileName num raw text
end
I could not test this code, since there was no sample data. Let me know if this works for you.
I want to import a sequence of excel files with a large amount of data in them. The problem that I have is I want to process the data in each file at a time and store the output from this into a variable, but each time I try to process a different file the variable gets overwritten in the variable workspace. Is there anyway I could store these files and process each file at a time?
numFiles = 1;
range = 'A2:Q21';
sheet = 1;
myData = cell(1,numFiles); % Importing data from Excel
for fileNum = 1:numFiles
fileName = sprintf('myfile%02d.xlsx',fileNum);
myData{fileNum} = importfile3(fileName,sheet,range);
end
data = cell2mat(myData);
The actual data import is performed by importfile3 which is, for the most part, a wrapper for the xlsread function that returns a matrix corresponding to the specified range of excel data.
function data = importfile3(workbookFile, sheetName, range)
% If no sheet is specified, read first sheet
if nargin == 1 || isempty(sheetName)
sheetName = 1;
end
% If no range is specified, read all data
if nargin <= 2 || isempty(range)
range = '';
end
%% Import the data
[~, ~, raw] = xlsread(workbookFile, sheetName, range);
%% Replace non-numeric cells with 0.0
R = cellfun(#(x) ~isnumeric(x) || isnan(x),raw); % Find non-numeric cells
raw(R) = {0.0}; % Replace non-numeric cells
%% Create output variable
data = cell2mat(raw);
The issue that you are running in to is a result of cell2mat concatenating all of the data in your cells in to one large 2-dimensional matrix. If you were to import two excel files with 20 rows and 17 columns, each, this would result in a 2-dimensional matrix of size [20 x 34]. The doc for cell2mat has a nice visual describing this.
I see that your importfile3 function returns a matrix, and based on your use of cell2mat in your final line of code, it looks like you would like to have your final result be in the form of a matrix. So I think the easiest way to go about this is to just bypass the intermediate myData cell array.
In the example code below, the resulting data is a 3-dimensional matrix. The 1st dimension indicates row number, 2nd dimension is column number, and 3rd dimension is file number. Cell arrays are very useful for "jagged" data, but based on the code you provided, each excel data set that you import will have the same number of rows and columns.
numFiles = 2;
range = 'A2:Q21';
sheet = 1;
% Number of rows and cols known before data import
numRows = 20;
numCols = 17;
data = zeros(numRows,numCols,numFiles);
for fileNum = 1:numFiles
fileName = sprintf('myfile%02d.xlsx',fileNum);
data(:,:,fileNum) = importfile3(fileName,sheet,range);
end
Accessing this data is now very straight-forward.
data(:,:,1) returns the data imported from your first excel file.
data(:,:,2) returns the data imported from your second excel file.
etc.