Looping over a Matlab structure - matlab

I am currently processing a bunch of files that I have imported into a structure, but have hit a bump in the road while trying to loop over the data.
First of all, here is my structure:
Ice
1.1 az160, az240, az300...
1.1.2 zen15, zen30,zen45...
1.1.2.1 Data
1.1.2.2 Textdata
I am trying to extract a value from each "textdata" cell array and use it to divide a column in data of the same structure. To do so, I am looping through the structure in the following way:
az_names = fieldnames(ice)
for m = 1:numel(az_names)
snames = fieldnames(ice.(az_names{m}))
for k = 1:numel(snames)
inttime = strrep(ice.(az_names{m}).(snames{k}).textdata(9,1), 'Integration > Time (usec): ','');
inttime = strrep(inttime, ' (USB2+E00040)','');
integration = cellfun(#str2num,inttime)
line 17 ice.(az_names{m}).(snames{k}).data(:,4) = ice.(az_names{m}).(snames{k}).data(:,3)/integration
end
end
I get the following error:
Index exceeds matrix dimensions
Edit: Matlab gives me the error at line 17. If I run the code up to "integration" and also write:
ice.(az_names{m}).(snames{k}).data(:,4)
I don't get a problem, Matlab prints to screen the right number and the data column.
I thought this would loop through each field in the structure and do the operation (dividing a column of values by a number), but I seem to be missing a point here. Can anybody see my mistake?
Regards,

If the error occurs when you try to execute this fragment:
ice.(az_names{m}).(snames{k}).data(:,4)
Then the cause is quite simple.
The variables m and k seem to be handled properly (due to the numel in the loop they should never be too big), meaning that the 4 is simply too big.
Check
ice.(az_names{m}).(snames{k}).data(:,4)
Or even more directly
size(ice.(az_names{m}).(snames{k}).data)
And you should find that the second element of the size is less than 4.
On second thought, this fragment works:
a.b=1;
a.b(:,4)=1
So I suspect that the error occurs when trying to read in this part:
ice.(az_names{m}). (snames{k}).data(:,3)
Meaning that the second element of the size should even be less than 3.
Also I would recommend removing the space.

Related

Why does variable stop increasing too early in Matlab loop?

I have the following code and error. Question follows below:
clear all, close all
%Reading data in from excel
[num,txt,raw] = xlsread('test.xlsx');
%Looking through the raw excel data to find all instances of 'Instruction: '
instructionindex = find(strcmp(raw,'Instruction: '));
%Making an array using a loop that takes the content of each cell in column 2, indexed by instructionindex
instruction = []
for i = 1:numel(instructionindex)
instruction = [instruction; raw{instructionindex(i),2}];
end
Error using vertcat
Dimensions of matrices being concatenated are not consistent.
Error in test2 (line 27)
instruction = [instruction; raw{instructionindex(i),2}];
and in the workspace I can see that while instructionindex is 24 x1 double, i only increases inside the loop to 7. That leads to a value (!) "instruction" of 6 x 5 char. I am not sure if this is somehow related to the fact that the content I am trying to bring together in the array "instruction" are strings.
My question: How can I get all the indexed 24 contents out in array "instruction" and what causes i to stop at 7?
EDIT: To further clarify why I think this is related to cells in column 2 containing strings: If I use
instruction = [instruction; raw{instructionindex(i),4}];
where column 4 contains numbers, everything works fine! I get two vectors of a size 24 each and concatenation works as well.

Splitting an audio file in Matlab

I'm trying to split an audio file into 30 millisecond disjoint intervals using Matlab. I have the following code at the moment:
clear all
close all
% load the audio file and get its sampling rate
[y, fs] = audioread('JFK_ES156.wav');
for m = 1 : 6000
[t(m), fs] = audioread('JFK_ES156.wav', [(m*(0.03)*fs) ((m+1)*(0.03)*fs)]);
end
But the problem is that I get the following error:
In an assignment A(I) = B, the number of elements in B and I
must be the same.
Error in splitting (line 12)
[t(m), fs] = audioread('JFK_ES156.wav', [(m*(0.03)*fs)
((m+1)*(0.03)*fs)]);
I don't see why there's a mismatch in the number of elements in B and I and how to solve this. How can I get past this error? Or is there just an easier way to split the audio file (maybe another function I don't know about or something)?
I think the easiest way to split audio is to just load it and use the vec2mat function. so you would have something like this;
[X,Fs] = audioread('JFK_ES156.wav');
%Calculate how many samples you need to capture 30ms of audio
matSize = Fs*0.3;
%Pay attention to that apostrophe. Makes sure samples are stored in columns
%rather than rows.
output = vec2mat(x,matSize)';
%You can now have your audio split up into the different columns of your matrix.
%You can call them by using the column calling command for matrices.
%Plot first 30ms of audio
plot(output(:,1));
%You can join the audio back together using this command.
output = output(:);
Hope that helps. Another good thing about this method is that it keeps all your data in one place!
Edit : One thing I thought of, you may get a problem with this depending on your vector size. But I think vec2mat actually zeroPads your vector. Not a big thing, but if you're moving back and forth between the two, then it might be a good idea to have another variable that stores the original length of your signal.
You should just use the variable y and reshape it to form your split audio. For example,
chunk_size = fs*0.03;
y_chunks = reshape(y, chunk_size, 6000);
That will give you a matrix with each column a 30 ms chunk. This code will also be faster than reading small segments from file in a loop.
As hiandbaii suggested you could also use cell array. Make sure you clear your existing variables before that. Not clearing the array t is probably the reason you got the error "Cell contents assignment to a non-cell array object."
Your original error is because you cannot assign a vector with scalar indexing. That is, 'm' is a scalar, but your audioread call is returning a vector. This is what the error says about mismatch in size of I and B. You could also fix that by making t a 2-D array and use an assignment like
[t(m,:), fs] =
It appears that each 30 ms segment is not equal to one sample. That would be the only case where your code works. i.e. 0.03*fs != 1.
You could try using cells instead.. i.e. replace t(m) with t{m}

Assigning arrays to a matrix in a function, syntax problems

I'm having trouble with the syntax in Matlab.
I'm trying to split an audio signal up into different segments (frames).
I would like to return the y-axis values to a matrix (each segment having its own column), and the corresponding time values with each segment having its own row.
I can't even get it to return just one single column and row pair (ie one frame). I just get returned two empty matrices. Here's my code.
function [mFrames, vTimeFrame] = Framing(vSignal,samplingRate,frameLPerc,frameshPerc)
totalTime=size(vSignal,1)/samplingRate
frameLength = totalTime*frameLPerc;
frameShift = totalTime*frameshPerc;
frameNumber =0;
check=frameLPerc;
while check<1
check = check+frameshPerc;
frameNumber=frameNumber+1;
end
start = 1;
% problem part
mFrames = vSignal(round((start:1/samplingRate:frameLength)*samplingRate));
vTimeFrame = round((start:1/samplingRate:frameLength)*samplingRate);
end
In the end I would like to be able to segment my entire signal into mFrames(i) and vTimeFrame(i) with a for-loop, but never mind that I cannot even get my function to return the first one (like I said empty matrix).
I know my segment code should be correct because I've got another script working with the same vSignal (it's a column vector by the way) that works just fine (y==vSignal):
voiced = y(round((1.245:1/Fs:1.608)*Fs));
plot(1.245:1/Fs:1.608,voiced)
I titled this with syntax problems because I'm very new to matlab and am used to Java. It feels very weird not initializing anything, and so I'm unsure whether my code is actually making any sense.
When testing I enter [m1,m2]=Framing(y,16000,0.1,0.05).
I got it.
start was not in the right domain. This is correct:
round((start/samplingRate:1/samplingRate:frameLength)*samplingRate)
When I plot(m2,m1) I now get the correct answer.
I do still have another question though, how can I assign these segments to my matrices?
for i=1:frameNumber
mFrames(:,i) = vSignal(round((start/samplingRate:1/samplingRate:frameLength)*samplingRate));
vTimeFrame(i) = round((start/samplingRate:1/samplingRate:frameLength)*samplingRate);
start=start+frameShift;
frameLength=frameLength+frameShift;
end
I get this error
In an assignment A(I) = B, the number of elements in B and I must be the same.
Like I said I'm trying to get the y-axis numbers in columns next to each other and the x-axis in rows.

Matlab Parse Error with a simple parenthesis?

I'm trying to finish a program and for some reason, the matrix I loaded into Matlab is messing with the ability to select the rows inside it. I'm trying to select all the rows in the matrix and see which values match the criteria for a Live setting. However I can select specific values/sections of the matrix in the command window without issue. Why is this happening? Any ideas?
It appears to only happen when in a for loop, I can do it just fine when it's on its own.
The syntax is: for x = start:stop. I think you are trying to do a for to the whole "A" matrix. You can split "A", according to its format (e.g. if is a table split in two variables).
bye
Richardd is right on; you're trying to iterate on a matrix, no good.
If I read you right, you're trying to run through your A matrix one column at a time, and see all the rows in that column? Assuming that is correct...
Your A matrix is 14x3, so you should go through your for loop 3 times, which is the size of your column dimension. Luckily, there is a function that MATLAB gives you to do just that. Try:
for iColumn = 1:size(A,2)
...
end
The size function returns the size of your array in a vector of [rows, columns, depth...] - it will go as many dimensions as your array. Calling size(A,2) returns only the size of your array in the column dimension. Now the for loop is iterating on columns.

Error with code when run in a loop but none when run outside a loop

Hi and thank you for viewing my question.
I have a large spreadsheet (over 650,000 rows) that I am trying to spit up into separate parts of a structure. I am trying to split it up by the values in one of the columns of which there is 1132 unique text values. The rest of the columns are numerical. I have created a matrix of the numerical values with 4 columns called 'SectionID_Matrix' and a cell array for the text column I want to split the data up by called 'ELR'. I am also trying to name the parts in the structure by the text value I have split them up by. My code is as follows:
ELR_list = unique (ELR);
[m,~]=size(ELR_list);
n = 1;
b = [];
for j = 1:m
x = strcmp(ELR_list(n), char(ELR));
b(:,1) = SectionID_Matrix(x(:,1),1);
b(:,2) = SectionID_Matrix(x(:,1),2);
b(:,3) = SectionID_Matrix(x(:,1),3);
b(:,4) = SectionID_Matrix(x(:,1),4);
t = char(ELR_list(n));
s.(t) = b;
n = n+1;
end
clearvars -except *ELR_list* *ELR* *SectionID_Matrix* *s*
When I run this code though I get an error saying 'Subscripted assignment dimension mismatch'. Error in Sorting_Out_Locations (line 10). b(:,1) = SectionID_Matrix(x(:,1),1);
This is confusing me because when I remove the for loop and manually change the value of n, it works perfectly fine giving me a matrix in the structure with all the rows that contain the nth text value with the name of the text value.
I understand the error is caused by attempting to assign more elements to a section of a matrix or vector than that section can hold but I don't understand where that is happening.
Is there an error in my code that is causing the for loop to fail? because from my limited understanding the loop should just keep going around increase n by 1 each time until it has gone through all of the unique ELR values.
This is my very first time on Matlab (so any pointer on my code are very appreciated) and have spend all afternoon trying to get this working but no amount of internet help or the matlab website is helping.
Thank you for any help
In your code, the first time it runs through the loop, the size of the b matrix is set according to the number of true values in x. The next time it runs through the loop, that may be a different size, so you get the mismatch.
You can just clear b at the end of each loop iteration with b = []
The error Subscripted assignment dimension mismatch appears when you try to insert a matrix of a certain size into a matrix of a different size. For your code, it means that in the line
b(:,1) = SectionID_Matrix(x(:,1),1);
there is an attempted insertion of mismatching sizes: the size of SectionID_Matrix(x(:,1),1) and the size of b(:,1) are not the same. This is most likely because you only take certain values of each column of SectionID_Matrix using the logical indexing of x. To fix this you need the same logical indexing in b:
b(x(:,1),1) = SectionID_Matrix(x(:,1),1);