How do I make a cell array of doubles with non-uniform dimensions into a row numeric array? (not a column numeric array)

8 views (last 30 days)
Hello, at the bottom of my code, which I pasted below, are two while loops in succession. The goal was to extract the doubles within the cells of the cell array, which only partially worked. I managed to make it a cell array of doubles, instead of a cell array of cells of doubles. However, the second loop gives the error message below:
Conversion to cell from double is not possible.
Error in Ralph_Hertz_5 (line 139)
step_response(:,n) = step_response{i};
If I go to the command window and type step_response = step_response{1}; I get the first cell's double inputted into step_response just as I want. I'm a bit miffed as to why I can't get the loop to do a similar thing. I have tried a variety of different arrangements. Any help is greatly appreciated as this is due Tuesday, thanks!
code below:
clear all;
close all;
fs = 10000;
input = load('input.mat');
input = input.input;
input1 = find(input>0, 1, 'first');
inputa = input';
output = load('output.mat');
output = output.output;
output = - output;
outputdiff = diff(output);
output1 = find(outputdiff < 0,1, 'first');
outputa = -output';
%aligns graphs for display purposes
i = length(inputa)-input1;
while i < length(inputa) - 2
inputa(:,1) = [];
end
input = inputa';
ti = (0:length(input) - 1)/fs;
i = length(outputa)-output1;
while i < length(outputa) - 1
outputa(:,1) = [];
end
output = outputa';
subplot(3,1,1)
plot(ti, input)
xlim([0 .05]);
hold on;
subplot(3,1,1)
to = (0:length(output) - 1)/fs;
plot(to, output)
title('Raw Signal of Step Response transposed over Input');
ylabel('Amplitude');
xlabel('Time(s)');
xlim([0 .05]);
%finds the maxima of the data, specificied to have a value higher than
%.492, and minimally 20 spaces apart
[pks_max, locs_max] = findpeaks(output,'MinPeakHeight',0.492,'MinPeakDistance',20);
output = -output;%negates function to find minima
%finds the minima of the data, specificied to have a value higher than
%.492, and minimally 20 spaces apart
[pks_min, locs_min] = findpeaks(output,'MinPeakHeight',0.492,'MinPeakDistance',20);
output = -output;
%makes matrices equal size, and aligns the beginning
locs_max = locs_max';
locs_max(:,1)=[];
locs_max = locs_max';
locs_min = locs_min';
locs_min(:,539) = [];
locs_min = locs_min';
i = 1;
n = 1;
%defines output2 as the noninverted portions of the signal.
%HOW DO I MAKE THIS INPUT INTO A NUMERICAL ARRAY?!
while i < length(locs_min);
output2{i} = output(locs_min(i):locs_max(i));
i = i + 1;
n = n + 1;
end
i = 1;
n = 1;
%defines output3 as the inverted portions of the signal.
%HOW DO I MAKE THIS INPUT INTO A NUMERICAL ARRAY?!
while i < length(locs_min)
output3{i} = output(locs_max(i):locs_min(i+1));
i = i + 1;
n = n + 1;
end
f = 1:(((length(output2)/100)-floor(length(output2)/100))*100);
%makes output2 an length dimension divisible by factors of 10
for i = 1 : length(f)
output2(:,(length(output2)-f(i))) = [];
end
f = 1:(((length(output3)/100)-floor(length(output3)/100))*100);
%makes output3 an length dimension divisible by factors of 10
for i = 1 : length(f)
output3(:,(length(output3)-f(i))) = [];
end
%negates output three, making inverted portions noninverted
output3 = gnegate(output3);
n = 1;
i = 1;
%sums split signal back into proper order
while i < length(output2)*2
step_response{i,1} = {output2{n}};
i = i + 1;
step_response{i,1} = {output3{n}};
i = i + 1;
n = n + 1;
end
n = 1;
i = 1;
%converts cell array of cell arrays into a cell array of numeric arrays
while i < length(step_response)+1
step_response(n) = step_response{i};
i = i + 1;
n = n + 1;
end
step_response = step_response';
%converts cell array of cell arrays into a cell array of numeric arrays
i = 1;
n = 1;
while i < length(step_response)+1
step_response(:,n) = step_response{i};
n = n +1;
i = i + 1;
end
  4 Comments
Stephen23
Stephen23 on 3 Nov 2015
Edited: Stephen23 on 4 Nov 2015
@Ralph Hertz: the volunteers here already have a good idea of how MATLAB can be used effectively, and what efficient MATLAB code looks like. However showing us buggy code does not help us to understand what you are trying to do. The only way that we can learn what you are trying to do is if you tell us this. Then we can give you advice, explain why, and show you how it can be coded effectively.
Consider editing your question to actually explain your needs:
"I have a numeric array of size MxN, each row corresponds to .... I need to extract the positive values, and plot these columns ...."
Do you see how this actually tells us what you need to do? Currently your code is very buggy, and it is not clear what you are trying to achieve with it.
And also please provide us with the actual (or fake) data that we can try out too. You can upload data using the paperclip button.
Guillaume
Guillaume on 4 Nov 2015
Below is Ralph's comment that I moved from the answer section:
This whole thing could be solved if I could get this for loop to work:
for i = 1 : (length(locs_min)*2) + 1;
output2(:,i+1) = output(locs_min(i):locs_max(i));
i = i + 1;
n = n + 1;
end
I keep getting this error:
|Subscripted assignment dimension mismatch.
Error in Ralphuh (line 74) output2(:,i+1) = output(locs_min(i):locs_max(i));|
output is a 53957 x 1 double array
locs_min and locs_max are both 1 x 538 double arrays...I have tried all sorts of tricks to get it to work...nothing doing.

Sign in to comment.

Accepted Answer

Stephen23
Stephen23 on 3 Nov 2015
Following your comment "It's a 1x1000 cell array, each with a double of between 50x1 and 52x1 in size. I want to either make all of the doubles the same length so I can use cell2mat, or use some other method of extracting the doubles from the cell arrays into a row matrix":
% data with unequal lengths:
X{3} = [9;10;11;12;13;14];
X{2} = [5;6;7;8];
X{1} = [1;2;3;4];
% merge data into matrix:
M = [];
for k = numel(X):-1:1
M(1:numel(X{k}),k) = X{k};
end
And the matrix looks like this:
>> M
M =
1 5 9
2 6 10
3 7 11
4 8 12
0 0 13
0 0 14

More Answers (3)

Stefan Raab
Stefan Raab on 2 Nov 2015
Try to create a new temporary variable for your new step_respone inside the while-loop. You want to convert the cell to a double, but the remaining elements of step_response are still cells. This won't work. Best regards, Stefan
  2 Comments
Ralph
Ralph on 2 Nov 2015
Hi Stefan, thank you for your response. I have tried defining a new variable instead of step_response, namely step_response1. I get this error:
>> Ralph_Hertz_5 Subscripted assignment dimension mismatch.
Error in Ralph_Hertz_5 (line 139) step_response1(i) = step_response{i};
when I do. Any suggestions how I could better define my loop to do this? Thanks!
Stefan Raab
Stefan Raab on 2 Nov 2015
step_response1(i) is just a single element in a double-array whereas step_response{i} is a double array itself. Try
step_response1(i,:) = step_response{i};
or
step_response1(:,i) = step_response{i};
Also you have to make sure, that the double array-cells have the same length, otherwise there will be an error as well.

Sign in to comment.


Guillaume
Guillaume on 4 Nov 2015
Edited: Guillaume on 4 Nov 2015
Following on your latest comment (please don't post comments as answers):
for i = 1 : (length(locs_min)*2) + 1;
output2(:,i+1) = output(locs_min(i):locs_max(i));
i = i + 1;
n = n + 1;
end
which gives you subscripted assignment mismatch. There could be several reasons for that. The first most obvious one would be that locs_mins(i) - locs_max(i) is not always the same, i.e. you're trying to copy a different number of elements column on each iteration of the loop.
assert(all(diff(locs_max - locs_min) == 0), 'Difference between locs_mins and locs_max is not constant')
If the above assert is not triggered, the reason may be that you're defined output2 with a wrong number of rows. You're not showing how you've initialised it.
Furthermore, in the above code the i=i+1 line has no effect. You cannot alter the sequence the iterator goes through within the loop. i will still iterates 1, 2, 3, ..., numel(locs_min)*2+1
It's also unclear what is the purpose of incrementing n within the loop, since it's not used there. You may just as well write outside the loop:
n = n + numel(locs_min)*2+1; %and avoid unnecessary parentheses as well.
  2 Comments
Ralph
Ralph on 8 Nov 2015
I was pretty exhausted, the comment as an answer was an accident...and I should have corrected the points you touched on in my for loop, but since they were of no functional consequence, and again I was exhausted, I didn't even notice it.
Ralph
Ralph on 8 Nov 2015
How would you initiate such a loop? I tried using a zero matrix to make a numeric array directly, but unless the lengths are the same it doesn't seem to be working. Have been messing with my indices and just about everything else within my for loop

Sign in to comment.


Thorsten
Thorsten on 4 Nov 2015
To write all of your data into a single matrix, you can use
Npeaks = numel(locs_max);
Ndata = locs_max - locs_min + 1;
allpeaks = nan(max(Ndata), Npeaks);
for i = 1:Npeaks
allpeaks(1:Ndata(i), i) = output(locs_min(i):locs_max(i));
end
Then the i'th column of allpeaks has the data of output between the i'th locs_min and locs_max (filled with NaNs to the maximum length of the data).
  1 Comment
Ralph
Ralph on 8 Nov 2015
I'm not sure you understand, although it may be I that don't understand. The locs_max and locs_min matrices are the same length. It's the distances between their indices in the output file that are of different length.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!