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

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

I find your code very confusing so I stopped trying to understand it. My advice would be to use better variable names than input, input1, inputa, etc. They're too vague in describing the purpose of the variable. Please see this page for some advice.(It's about the python language but is just as valid for matlab or any other language).
In addition, input is a built-in function of matlab, so that should never be used for a variable name.
Also, what is the purpose of
locs_max = locs_max';
locs_max(:,1)=[];
locs_max = locs_max';
It's the same as
locs_max(1, :)=[]; %just transpose the indices, rather than the matrix
I'm unclear on what data structure you start with and what data structure you want. In part of your post you say you wanted a cell array of cells of doubles (is that a cell array of cell arrays of a double matrices?), but at the beginning you say you want to extract doubles (matrices?) from a cell array.
Rather than posting code that don't work, why don't you describe your input (a cell array of double matrices?) and the output you want (a matrix? obtained by concatenating all the matrices vertically?)
In all likely, what you want can be achieved with only one or two lines of code.
I'm very new to matlab, sorry for the confusion. I have a cell array of doubles, which is defined as "step_response". 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. Thanks
@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.
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

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

1 Comment

Sorry, I'm just getting back to this...it has been an intense week, but that made a huge difference for me, thanks!

Sign in to comment.

More Answers (3)

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

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!
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.

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

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.
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.

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

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.

Asked:

on 2 Nov 2015

Commented:

on 8 Nov 2015

Community Treasure Hunt

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

Start Hunting!