Use row vector index values to select a matrix portion. Error: Index exceeds matrix dimensions.

1 view (last 30 days)
Hello guys,
I have managed to determine a threshold to cut a set of signals stored in a matrix where each column represents an independent signal, the goal is to synchornise all signals according to this threshold. I have then created a row vector (1x10) containing the index reflecting that threshold. All good but when it comes to cut the signal I have got stuck. the second for loop does not work. I'm expecting to obtain a matrix containing columns where in that specific case the first value of each column (each signal) is >1. 'Data' in my case is a matrix 5001x10, whereas 'data_synch' is expected to be 'data' but starting >1 for each different column (e.g. 150x10).
ncol = size(data,2);
threshold=ones(1,ncol);
for k=1:ncol
idx_start(:,k)=find(data(:,k)>threshold(:,k),1);
end
for k=1:ncol
data_synch(:,k)=data(idx_start(k):idx_start(k)+timePost,k);
end
Index exceeds matrix dimensions.
  4 Comments

Sign in to comment.

Answers (2)

Jan
Jan on 27 Jul 2018
Edited: Jan on 27 Jul 2018
My guess is, that your data does not have idx_start(k)+timePost elements. Use the debugger to test this:
dbstop if error
Type this in the command window and run the code again. When it stops, check the value of k and idx_start(k)+timePost

Guillaume
Guillaume on 27 Jul 2018
Nearly every single line of code is a potential problem.
threshold=ones(1:ncol);
Hopefully this is a typo in your question and not actual code. The above will create a matrix of size 1x2x3x4x...xncol, so the matrix created will have factorial(ncol) elements. For ncol = 10, it's not a problem, it's only ~27 MB. For ncol = 11, it's already 300 MB, 3.5 GB for ncol = 12 and 46 GB for ncol = 13.
Let's assume you meant
threshold = ones(1, ncol);
Now since threshold is the same for all columns we've got to wonder why it's vector. You could just as well do
threshold = 1;
and not index it all in the loop.
Then,
idx_start(:,k)=find(data(:,k)>threshold(:,k),1);
idx_start has not been preinitialised. The instruction above will put one element per column. If idx_start already exist and is more than one row, it will replicate the result of find across all the rows. Not what was intended, thankfully it would have no ill effect (other than wasting time). Since it's evident that idx_start is supposed to be a row vector, the above should have been:
idx_start = zeros(1, ncol); %preinitialisation
for k = 1:ncol
idx_start(k) = ...
On the same line, we have
find(..., 1)
This is guaranteed to return at most one value. It can also return nothing at all if nothingd match your condition. Trying to assign nothing to something will raise an error. Therefore before the loop I would have
assert(~any(data > threshold), 'At least one column does not have any element greater than the threshold');
to make sure than all columns have at least one element greater than its corresponding threshold.
Finally, on the same lines we have:
threshold(:,k)
I'm fairly certain you didn't mean all the rows of the kth column (which is what the : mean).If threshold is a vector, threshold(:, k) is the same as treshold(1, k) which is the same as threshold(k).
In the next loop we have:
data_synch(:,k)= ...
Again, no preinitialisation if data_synch has less than timePost rows, it will be grown to timePost rows, not too much of a problem other than wasted time. If it has more rows, you'll get a dimension mismatch error.
Then we have
... data(idx_start(k):idx_start(k)+timePost, k)
Of course if the location of the threshold is less than timePost rows from the last row, idx_start(k)+timePost will end up past the array. Most likely the reason for the Index exceeds matrix dimensions you get.
The whole lot can probably be achieved without any loop, certainly the first part doesn't need a loop but we would need to know what you want to do when the threshold is closer than timePost rows from the last row since it won't be possible to extract timePost rows in that column.
  3 Comments
Guillaume
Guillaume on 29 Jul 2018
I'm a bit confused. Unless your threshold is met on exactly the same rows for all columns, the bit you cut won't be the same length for each column.
Unless you only keep 150 samples after the threshold for each row? In that case, you need to explain what should happen if the threshold is found closer than 150 samples from the end.
Giuseppe
Giuseppe on 29 Jul 2018
Correct. The same threshold applies to each column. The signal is recorded in a way to ensure 150 points will always be available after the threshold.

Sign in to comment.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Products


Release

R2014a

Community Treasure Hunt

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

Start Hunting!