How to Scale Array Indices to larger array indices?

10 ビュー (過去 30 日間)
Jacob Franklin
Jacob Franklin 2019 年 8 月 22 日
コメント済み: Jacob Franklin 2019 年 8 月 26 日
Okay, suppose I have logical/TTL square wave array that looks something like this.
t = [0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0];
It is a scaled down representation of a much larger array with a 1:68608 scaling. I.e. here value 2 is at index 2 but in the larger array index 2 would start at 68608 + 1
I need to get the scaled indices of all the 0 and 1 sections for indexing the larger array. What I have been doing so far is getting the edge indices using strfind(t, [0 1]) and strfind(t, [1 0]) and multiplying them by the scaling factor to get the correct scaled indices for the edges and then some stuff with find(cumsum()) to get inclusive indices which gets me close by I am usually missing a unit or so because this wont include edges.
I just need a way to mathematically scale these indices. So instead of 6:10 and 16:20 I have 343041:686080 and 1029121:1372160 but in a way that will also include edges if for example I needed 1:5, 11:15, and 21 in which case 21 wouldn't just be 21 but 1372161:1440768.
Which has been the pit fall of my cum sum method so far as 21 just scales to 21 and doesnt give me a range except 21:21.
Edit to add a software example (ignore redunant logic, this was something I was playing with):
function [idx, numVals] = giveIndices(t)
valsPerUnit = 100;
numVals = valsPerUnit*numel(t);
starts = strfind(t, [0 1]);
stops = strfind(t, [1 0]);%+1;
if stops(1) < starts(1)
starts = [1 starts+1];
if starts(end) > stops(end)
if starts(end) < numel(t)
stops(end+1) = numel(t);%+1;
else
stops(end+1) = numel(t);
end
else
end
starts = starts*valsPerUnit;
starts = starts-(valsPerUnit-1);
stops = stops*valsPerUnit+1;
k = [];
k(starts) = -1;
k(stops) = 1;
idx = find(cumsum(k));
else
starts = starts*valsPerUnit+1;
stops = stops*valsPerUnit+1;
k = [];
k(starts) = -1;
k(stops) = 1;
idx = find(cumsum(k));
end
end
This will give you the correct indices for most circumstance but not always. For example this will work if t = [0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0] & t= [1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1], but will fail for t = [0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1] because it wont get the ends.
  3 件のコメント
Jacob Franklin
Jacob Franklin 2019 年 8 月 22 日
Thats all well and good, but then I need to scale those indices up and get all scaled indices inbetween.
For example I can do that on the t given and I will get 6 11 16 21
But lets say my scaled array was 100 elements per every 1 element. Okay so I can multiply by 100 and get 600, 1100, 1600, 2100. But its not sufficient to just have those indices, I need everything included therein, that is 600:1100 and 1600:2100
David Hill
David Hill 2019 年 8 月 23 日
idx=find(abs(diff(t))+1;
idx=[idx,length(t)+1];
scaled_idx=scaling*idx;
finalMatrix=[];
Length=1;
for i=1:length(idx)
if t(idx(i)-1)
finalMatrix=[finalMatrix,ones(1,scaled_idx(i)-Length)];
else
finalMatrix=[finalMatrix,zeros(1,scaled_idx(i)-Length)];
end
Length=scaled_idx(i);
end
I think the above will give you what you want.

サインインしてコメントする。

採用された回答

Stephen23
Stephen23 2019 年 8 月 23 日
編集済み: Stephen23 2019 年 8 月 23 日
Here is one simple approach based on diff and find. Because a scaling factor of 68608 is rather inconvenient I used a scaling factor of 3.
>> t = [0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,0]; % small vector.
>> k = 3; % scaling factor: large/small.
>> D = diff([false,t==1,false]); % small detect 1's.
>> B = k*(find(D>0)-1)+1 % large begin of 1's.
B =
16 46
>> E = k*(find(D<0)-2)+k % large end of 1's.
E =
30 60
Check these against the large vector, for integer scaling factors we can use repelem or kron, e.g.:
>> z = kron(t,ones(1,k)) % large vector.
z =
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0
>> D = diff([false,z==1,false]); % large detect 1's.
>> find(D>0) % large begin of 1's.
ans =
16 46
>> find(D<0)-1 % large end of 1's.
ans =
30 60
Detecting the 0's I leave as a simple exercise for the reader.
  1 件のコメント
Jacob Franklin
Jacob Franklin 2019 年 8 月 26 日
I am accepting this as the answer because when given the correct inputs find(kron(t,ones(1,k))) does EXACTLY what I need.
My final solution formulates the scaled down logical array using a weighted mask and mod()
weightedMasked = [zeros(1, N)] ones(1, N)]; % N = 5 so [0 0 0 0 0 1 1 1 1 1];
elementNumbers = startNum:endNum; % Doing this in chunks so start of chunk to end of chunk
elementWeights = mod(elementNumbers, N*2) + 1; % +1 b/c index at 1 not 0 -> result is [1 2 3 4 5 6 7 8 9 10 1 2 4 5 6 7 8 9 10..etc]
scaledDownLogical = wieghtedMask(elementWeights);
scaledUpLogicalIdxs = find(kron(scaledDownLogica, ones(1, valsPerElement)));

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeMatrix Indexing についてさらに検索

タグ

製品

Community Treasure Hunt

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

Start Hunting!

Translated by