How to approach iterative data reading?

I'm working with a dataset that has 3 different arrays I'm interested in plotting: time, accel, and gcamp. They are all of equal size.
I'm using the accel variable as a threshold detector, where I define an arbitrary threshold under which any data I ignore. Anything above that threshold I use the index of that data point to grab the equivalent data points from time and gcamp.
How can I store this data in one structure so that I can iterate through it and generate statistics/plots about only the thresholded data points?
Something like:
time = [rand(1, 5000)];
accel = [rand(1,5000)];
gcamp = [rand(1,5000)];
sd = std(accel);
threshold = sd;
dumb = [];
for i = 1:length(accel);
if accel(i) > threshold;
dumber = [time(i), gcamp(i)];
dumb = [dumb, dumber];
end
end

 Respuesta aceptada

Hi Eric,
Use logical indexing.
time = [rand(1, 5000)];
accel = [rand(1,5000)];
gcamp = [rand(1,5000)];
sd = std(accel);
threshold = sd;
dumb = [];
for i = 1:length(accel);
if accel(i) > threshold;
dumber = [time(i), gcamp(i)];
% dumb = [dumb, dumber];
dumb = [dumb; dumber];
end
end
index = accel > threshold;
foo = [time(index);gcamp(index)].'; % transpose to match dumb
isequal(foo,dumb)
ans = logical
1

Más respuestas (1)

Star Strider
Star Strider hace alrededor de 22 horas
I am not certain what you want to do, however the logical vector approach (the 'Lv' variable here) is probably more efficient that the explicit loop.
One option to segregate the values after threshoding them is to find the beginning and end locations of each series of 1 values in Lv and use that to segment the signal. You can do whatever you want with the segments after that.
Try something like this --
% time = [rand(1, 5000)];
time = 0:4999;
accel = sin(time*2*pi/500);
gcamp = cos(time*2*pi/400);
sd = std(accel);
threshold = sd;
Lv = accel > threshold;
Valid = nnz(Lv)
Valid = 1250
timev = time(Lv);
gcampv = gcamp(Lv);
% Lv
startv = strfind(Lv, [0 1]) + 1;
stopv = strfind(Lv, [1 0]);
if startv(1) > stopv(1)
startv = [1 startv];
end
if numel(startv) > numel(stopv)
stopv = [stopv numel(Lv)];
end
for k = 1:numel(startv)
idxrng = startv(k):stopv(k);
ixr{k} = idxrng([1 end]);
segment{k} = [time(idxrng); gcamp(idxrng)];
end
ixr{1}
ans = 1×2
64 188
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
segment{1}
ans = 2×125
63.0000 64.0000 65.0000 66.0000 67.0000 68.0000 69.0000 70.0000 71.0000 72.0000 73.0000 74.0000 75.0000 76.0000 77.0000 78.0000 79.0000 80.0000 81.0000 82.0000 83.0000 84.0000 85.0000 86.0000 87.0000 88.0000 89.0000 90.0000 91.0000 92.0000 0.5490 0.5358 0.5225 0.5090 0.4955 0.4818 0.4679 0.4540 0.4399 0.4258 0.4115 0.3971 0.3827 0.3681 0.3535 0.3387 0.3239 0.3090 0.2940 0.2790 0.2639 0.2487 0.2334 0.2181 0.2028 0.1874 0.1719 0.1564 0.1409 0.1253
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
ixr{2}
ans = 1×2
564 688
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
segment{2}
ans = 2×125
563.0000 564.0000 565.0000 566.0000 567.0000 568.0000 569.0000 570.0000 571.0000 572.0000 573.0000 574.0000 575.0000 576.0000 577.0000 578.0000 579.0000 580.0000 581.0000 582.0000 583.0000 584.0000 585.0000 586.0000 587.0000 588.0000 589.0000 590.0000 591.0000 592.0000 -0.8358 -0.8443 -0.8526 -0.8607 -0.8686 -0.8763 -0.8838 -0.8910 -0.8980 -0.9048 -0.9114 -0.9178 -0.9239 -0.9298 -0.9354 -0.9409 -0.9461 -0.9511 -0.9558 -0.9603 -0.9646 -0.9686 -0.9724 -0.9759 -0.9792 -0.9823 -0.9851 -0.9877 -0.9900 -0.9921
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
ixr{end}
ans = 1×2
4564 4688
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
segment{end}
ans = 2×125
1.0e+03 * 4.5630 4.5640 4.5650 4.5660 4.5670 4.5680 4.5690 4.5700 4.5710 4.5720 4.5730 4.5740 4.5750 4.5760 4.5770 4.5780 4.5790 4.5800 4.5810 4.5820 4.5830 4.5840 4.5850 4.5860 4.5870 4.5880 4.5890 4.5900 4.5910 4.5920 -0.0008 -0.0008 -0.0009 -0.0009 -0.0009 -0.0009 -0.0009 -0.0009 -0.0009 -0.0009 -0.0009 -0.0009 -0.0009 -0.0009 -0.0009 -0.0009 -0.0009 -0.0010 -0.0010 -0.0010 -0.0010 -0.0010 -0.0010 -0.0010 -0.0010 -0.0010 -0.0010 -0.0010 -0.0010 -0.0010
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
figure
hold on
for k = 1:numel(segment)
plot(segment{k}(1,:), segment{k}(2,:))
end
hold off
grid
showMissing = zeros(size(time)) - 0.2;
showMissing(Lv) = 0.2 * ones(1,Valid);
figure
plot(time, gcamp)
hold on
plot(time, showMissing, 'r')
hold off
grid
figure
stairs(time, gcamp, '-')
hold on
stairs(time, showMissing, '-r')
hold off
grid
xlim([1000 1900])
ylim([-1.1 1.1])
% dumb = [];
% for i = 1:length(accel);
% if accel(i) > threshold;
% dumber = [time(i), gcamp(i)];
% dumb = [dumb, dumber];
% end
% end
.

3 comentarios

Eric
Eric hace 34 minutos
i fear i don't think these plots have relevance for me, and maybe i'm just missing something.
to start, why are you using strfind when you're not indexing through strings? why not use find?
i can't tell if this is so high level it's beyond my comprehension or this is ai generated code
Star Strider
Star Strider hace 19 minutos
It's not generated code. I wrote it. It's original to your question, although I've used similar code for similar problems..
I use strfind because it works in this instance. There are other ways to test for the beginning and end of the 1 series occurrences, however this is the easiest and most efficient.
With respect to the plots, they simply illustrate what my code does, considering that you stated 'How can I store this data in one structure so that I can iterate through it and generate statistics/plots about only the thresholded data points?' The 'one structure' in my code is the 'segments' cell array. (I chose that name rather than 'dumber'. Change its name to whatever you want.)
My code might have to be tweaked slightly to work precisely with your data, however in all likelihood, it should work without modification. Remove the two if blocks if you don't need them.
It turns out that strfind has a no-longer-documented behaviour of searching for patterns in numeric arrays.
strfind(NUMERIC_ARRAY, PATTERN)
has the behaviour of searching within NUMERIC_ARRAY looking for positions that match the contents of PATTERN, locations where
all(NUMERIC_ARRAY(K:K+length(PATTERN)-1) == PATTERN(1:end))
and returning all of the K that the condition matches for.
It is common to use this to match between two logical arrays, or between double precision arrays and logical arrays, such as
strfind(X >= 1, [0 1 1 1])
being the command to search X for transitions between values less than 1 and a group of at least 3 places that are greater than or equal to 1. Likewise,
strfind(X >= 1, [1 1 1 0])
would search for locations where at least 3 positions in a row were greater than or equal to 1, followed by a position where the condition was false.
When you put two strfind() together, you can get the locations of starts of runs in one call, and the locations of ends of runs in another call.
You do have to be careful to add (one less than the length of the pattern) to the returned indices to get the actual location of the ends of runs. You have to double-check the logic to distinguish between the last location that is within a run, compared to the first location that is after the run, both of which are valid things to want to search for.
@Star Strider uses comparison logic to determine boundary conditions. I personally prefer to use logic such as
strfind([false, X>= 1], [0 1 1 1])
if I want leading runs of >= 1 to be considered to match. After all, there are times when (for example)
[3 8 2 1 -2 -1 4 9 13]
sometimes you want the pattern X>=1 to be considered to start immediately at the beginning of the array, and sometimes you do not want it to be considered to start until the -1 4 9 13

Iniciar sesión para comentar.

Categorías

Más información sobre MAB Modeling Guidelines en Centro de ayuda y File Exchange.

Preguntada:

hace alrededor de 24 horas

Comentada:

hace 1 minuto

Community Treasure Hunt

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

Start Hunting!

Translated by