Splitting arrays in matlab - arrays

Greetings All
I'm trying to
1)split an array into multiple parts
2)export each part to separate wave files
3)re-import wav files and join them together to make sure
the array data that was split up wasn't altered.
I can do all of these steps the problem is when I test for
error I expect it should be something like 2.232e-15 which
is almost no error however I get unexpected large numbers
for error.
MAE = 0.046232
MXE = 0.14522
RMSE = 0.064035
How can I fix this so the error rate goes down?
I thought the array was being split in sections and the cell data was being copied
exactly but it's looking like that may not be the case,
how can I fix this?
Code below:
%split_file
%create sine wave signal
clear all, clc
tic
fs = 44100; % Sampling frequency
t=linspace(0,1,fs);
freq=340;
ya = sin(2*pi*freq*t); %+ 1*sin(2*pi*250*t);
[size_r,size_c]=size(ya');
jj=[];
kk=0;
wavefilesplit=[];
%need to delete diretory and recreate it to clean out files
fileprepathStr='/home/rat/Documents/octave/pre/'; %
rmdir(fileprepathStr,'s');
fprintf('\n-1- deleting %s directory %2.4f sec',fileprepathStr,toc);
mkdir(fileprepathStr);
fprintf('\n-1- creating %s directory %2.4f sec',fileprepathStr,toc);
jj=1;
for ii=1:fs/4:size_r, %build array of desired ranges or fs/2
jj(end+1,:)=ii-1; %minus 1 to get correct array index in cell
end;
[size_rjj,size_cjj]=size(jj); %used to get size of jj array
jj(end+1,:)=size_r-(size_rjj-2); %adds the end of the sound file to the end of the jj array minus the amount of files joined
jj(2,:)=[]; %deletes second cell with zero and shifts the cells up
for ii=1:1:size_rjj-1,kk=kk+1;
wavefilesplit=ya(jj(kk):jj(kk+1));
wavefn=strcat('wavefn_',num2str(kk,'%04d')); %build filename dynamiclly with 4 leading zeros
wavwrite([wavefilesplit],fs,16,strcat('/home/rat/Documents/octave/pre/',wavefn,'.wav'));
fprintf('\n-1- wavwrite split %s.wav %3.0f of %3.0f %6.3fsec %6.3fmins\n',wavefn,kk,size_rjj-1,toc,toc/60);
end;
fprintf('\n-2- Elapsed time in seconds after wavwrite split %6.3fsec %6.3fmins\n',toc,toc/60);
%rejoin to check if arrays are the same
y2=[]; %
yb2=[];
filepathprocStr='/home/rat/Documents/octave/pre/';
files2=strcat(filepathprocStr,'*.wav');
files2=dir(files2);
[rwsz_files2,clsz_files2]=size(files2); %used to get ro and col size
for i=1:numel(files2)
[yb2, fs2, nbits] = wavread(strcat(filepathprocStr,files2(i).name));
yb2=yb2';
y2=[y2;yb2]; %Append files2
fprintf('\n %4.0f of %4.0f joined %s',i,rwsz_files2,files2(i).name)
end;
wavwrite([y2],fs2,16,'/home/rat/Documents/octave/pre/All_joined.2wav')
fprintf(' \n Done!!!\n');
ya=ya';
dy = abs(ya-y2); % absolute error
MAE = mean(dy) % 7.2292e-015 mean-absolute-error
MXE = max(dy) % 3.4195e-014 maximum-absolute-error
RMSE = sqrt(mean(dy.^2)) % 9.5049e-015 root-mean-sqare-error

I decided to use the reshape command and pad with zeros because it cuts the code down a lot and it should be quicker.
clear all, clc
ya=1:64;
fs=9;
padlen = mod(-length(ya), fs); %creates number of zeros needed to get correct array reshaped
ya_reshaped = reshape([ya zeros(1,padlen)], fs, []); % used to pad zeros on 1 col x rows
[size_r,size_c]=size(ya_reshaped)
wavefilesplit=[];
wavefilesplit2=[];
for ii=1:size_c
wavefilesplit=ya_reshaped(:,ii) %this line can be used to export data/audio to file
%could use if else statment to strip zeros off end if inserted here
wavefilesplit2=[wavefilesplit2; ya_reshaped(:,ii)] %will append to end all in one col to error check
end;
wavefilesplit2(end-(padlen-1):end)=[] %will erase zeros at the end of array wavefilesplit2(end-(padlen-1):end,1)=2 will ad 2's

Related

matlab: logically comparing two cell arrays

I have an excel file from which I obtained two string arrays, Titles of dimension 6264x1 and another Names of dimension 45696x1. I want to create an output matrix of size 6264x45696 containing in the elements a 1 or 0, a 1 if Titles contains Names.
I think I want something along the lines of:
for (j in Names)
for (k in Titles)
if (Names[j] is in Titles[k])
write to excel
end
end
end
But I don't know what functions I should use to achieve what I have in the picture. Here is what I have come up with:
[~,Title] = xlsread('exp1.xlsx',1,'A3:A6266','basic');
[~,Name] = xlsread('exp1.xlsx',2,'B3:B45698','basic');
A = cellstr(Title);
GN = cellstr(Name);
BinaryMatrix = false(45696,6264);
for i=1:1:45696
for j=1:1:6264
if (~isempty(ismember(A,GN)))
BinaryMatrix(i,j)= true;
end
end
end
the problem with this code is that it never finishes running, although there are no suggestions within matlab.
You can use third output of unique to get numbers corresponding to each string element and use bsxfun to compare numbers.
GN = cellstr(Name);
A = cellstr(Title);
B = [ GN(:); A(:)];
[~,~,u]= unique(B);
BinaryaMatrix = bsxfun(#eq, u(1:numel(GN)),u(numel(GN)+1:end).');
ismember can handle cell arrays of character vectors. Its second output tells you the information you need, from which you can build the result using sparse (it could also be done by preallocating and using [sub2ind):
[~, m] = ismember(Titles, Names);
BinaryMatrix = full(sparse(nonzeros(m), find(m), true, numel(Names), numel(Titles)));

How can I concatenate the arrays in loop ? Matlab

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.

Trimming vals in a matrix of arbitrary dimensions in a specified dimension

I'm writing a function that requires some values in a matrix of arbitrary dimansions to be dropped in a specified dimension.
For example, say I have a 3x3 matrix:
a=[1,2,3;4,5,6;7,8,9];
I might want to drop the third element in each row, in which case I could do
a = a(:,1:2)
But what if the dimensions of a are arbitrary, and the dimension to trim is defined as an argument in the function?
Using linear indexing, and some carefully considered maths is an option but I was wondering if there is a neater soltion?
For those interested, this is my current code:
...
% Find length in each dimension
sz = size(dat);
% Get the proportion to trim in each dimension
k = sz(d)*abs(p);
% Get the decimal part and integer parts of k
int_part = fix(k);
dec_part = abs(k - int_part);
% Sort the array
dat = sort(dat,d);
% Trim the array in dimension d
if (int_part ~=0)
switch d
case 1
dat = dat(int_part + 1 : sz(1) - int_part,:);
case 2
dat = dat(:,int_part + 1 : sz(2) - int_part);
end
end
...
It doesn't get any neater than this:
function A = trim(A, n, d)
%// Remove n-th slice of A in dimension d
%// n can be vector of indices. d needs to be scalar
sub = repmat({':'}, 1, ndims(A));
sub{d} = n;
A(sub{:}) = [];
This makes use of the not very well known fact that the string ':' can be used as an index. With due credit to this answer by #AndrewJanke, and to #chappjc for bringing it to my attention.
a = a(:, 1:end-1)
end, used as a matrix index, always refers to the index of the last element of that matrix
if you want to trim different dimensions, the simplest way is using and if/else block - as MatLab only supports 7 dimensions at most, you wont need an infinite number of these to cover all bases
The permute function allows to permute the dimension of an array of any dimension.
You can place the dimension you want to trim in a prescribed position (the first, I guess), trim, and finally restore the original ordering. In this way you can avoid running loops and do what you want compactly.

Creating sub-arrays from large single array based on marker values

I need to create a 1-D array of 2-D arrays, so that a program can read each 2-D array separately.
I have a large array with 5 columns, with the second column storing 'marker' data. Depending on the marker value, I need to take the corresponding data from the remaining 4 columns and put them into a new array on its own.
I was thinking of having two for loops running, one to take the target data and write it to a cell in the 1-D array, and one to read the initial array line-by-line, looking for the markers.
I feel like this is a fairly simple issue, I'm just having trouble figuring out how to essentially cut and paste certain parts of an array and write them to a new one.
Thanks in advance.
No for loops needed, use your marker with logical indexing. For example, if your large array is A :
B=A(A(:,2)==marker,[1 3:5])
will select all rows where the marker was present, without the 2nd col. Then you can use reshape or the (:) operator to make it 1D, for example
B=B(:)
or, if you want a one-liner:
B=reshape(A(A(:,2)==marker,[1 3:5]),1,[]);
I am just answering my own question to show any potential future users the solution I came up with eventually.
%=======SPECIFY CSV INPUT FILE HERE========
MARKER_DATA=csvread('ESphnB2.csv'); % load data from csv file
%===================================
A=MARKER_DATA(:,2); % create 1D array for markers
A=A'; % make column into row
for i=1:length(A) % for every marker
if A(i) ~= 231 % if it is not 231 then
A(i)=0; % set value to zero
end
end
edgeArray = diff([0; (A(:) ~= 0); 0]); % set non-zero values to 1
ind = [find(edgeArray > 0) find(edgeArray < 0)-1]; % find indices of 1 and save to array with beginning and end
t=1; % initialize counter for trials
for j=1:size(ind,1) % for every marked index
B{t}=MARKER_DATA(ind(j,1):ind(j,2),[3:6]); % create an array with the rows from the data according to indicies
t=t+1; % create a new trial
end
gazeVectors=B'; % reorient and rename array of trials for saccade analysis
%======SPECIFY MAT OUTPUT FILE HERE===
save('Trial_Data_2.mat','gazeVectors'); % save array to mat file
%=====================================

Matlab Assigning Elements to Array in loop

I have this loop which generates a vector "Diff". How do I place the values of Diff in an array that records all the Diff's generated? The problem is that the length of Diff should be a fixed length (36) which is the width of the table "CleanPrice". But because col_set varies in length (according to the number of NaNs in the data it is reading), then Diff also varies in length. What I need it to do is assign the answers generated according to their appropriate column number. i.e. row(i) of diff should contain col(i) where all other rows in Diff should be assigned a "0" or "NaN". Basically I need DiffArray to be a (nTrials x 36) array where each row is the (36 x 1) DiffArray generated. At the moment though, each time the length of col changes, I get the following error:
??? Subscripted assignment dimension mismatch.
Error in ==> NSSmodel
at 41 DiffMatrix(end+1,:)=Diff
This is my code:
DiffArray=[];
StartRow=2935;
EndRow=2940;
nTrials=EndRow-StartRow;
for row=StartRow:EndRow;
col_set=find(~isnan(gcm3.data.CleanPrice(row,1:end)));
col=col_set(:,2:end);
CleanPrices=transpose(gcm3.data.CleanPrice(row,col));
Maturity=gcm3.data.CouponandMaturity(col-1,2);
SettleDate=gcm3.data.CouponandMaturity(row,3);
Settle = repmat(SettleDate,[length(Maturity) 1]);
CleanPrices =transpose(gcm3.data.CleanPrice(row,col));
CouponRate = gcm3.data.CouponandMaturity(col-1,1);
Instruments = [Settle Maturity CleanPrices CouponRate];
PlottingPoints = gcm3.data.CouponandMaturity(1,2):gcm3.data.CouponandMaturity(36,2);
Yield = bndyield(CleanPrices,CouponRate,Settle,Maturity);
SvenssonModel = IRFunctionCurve.fitSvensson('Zero',SettleDate,Instruments)
ParYield=SvenssonModel.getParYields(Maturity);
[PriceActual, AccruedIntActual] = bndprice(Yield, CouponRate, Settle, Maturity);
[PriceNSS, AccruedIntNSS] = bndprice(ParYield, CouponRate, Settle, Maturity);
Diff=PriceActual-PriceNSS
DiffArray(end+1,:)=Diff
end
I looked at num2cell in this post but wasn't sure how to apply it correctly and started getting errors relating to that instead.
Is it correct to say you want to add an 'incomplete' row to DiffArray? If you know exactly where each element should go you could maybe do something like this:
indices = [1:7; 2:8; 3:9; [1 2 3 6 7 8 10]];
Diff = rand(4, 7);
DiffArray = zeros(4, 10) * NaN;
for row = 1:4
DiffArray(row, indices(row, :)) = Diff(row,:);
end
of course in your case you would be calculating Diff and Index (a row vector) inside the loop and not using preassigned arrays. The above is just to illustrate how to use an indexing vector to position a short row in a matrix.

Resources