- Identify 3% drops.
- Identify 3% rises.
- Identify drop-to-rise runs.
- Filter these runs based on length.
Extract segments from signal
14 vues (au cours des 30 derniers jours)
I have a signal in form of a 6608x1 double and I'd like to extract segments from that signal.
I want to extract every segment of the signal where the signal drops by at least 3% compared to the prior max value. Also, the segments are only valid if the duration is at least 150 seconds. As soon as the signal goes up again, the segment is over. I want to store these segments in a seperate array, so I can plot these segments on top of the signal to highlight where the signal drops by at least 3% for at least 150 seconds.
Can someone help me define the criteria for this task in Matlab? I'm not quite sure how to approach this.
This is a drawing of how I would like this to look when I plot the segments on top of the signal.
Thanks in advance!
Daniel le 24 Mai 2023
As a caution, I'm not at all sure that this is the most efficient way to do what you're asking. That said, it looks like you want to do a couple of things:
At some point you'll also need to associate time values with your data. You can do this by creating a time vector, such as
Based on your plot, it looks like you're taking samples once a second, so Ts would be 1.
To identify drops, you'll need to take the difference and compare it to the former value. You can take the difference with the diff function.
signal_difference = [diff(signal);0]; % I'm adding an element so sigdiff has the same size as signal
signal_ratio = signal_difference./signal; % Element-wise normalization gives you the relative differences
Then you'll want to identify falling and rising edges by comparing signal_ratio to 0.03 or -0.03. (By the way, your provided signal data contains no 3% drops or rises.)
Next, you'll have to iterate over the drops and rises to collect them. You'll often see multiple drops before a single rise, or multiple rises before a single drop. So you'll need to write some sort of state machine to pair them, looking for a drop and then looking for a rise and so on. If you store the index associated with each qualified drop and each qualified rise, that will allow you to extract the signal data, and also give you the run length for each run. I'm not aware of anything prefabricated that does this automatically.
Finally, scan that list of indices and reject any run length less than your desired time.
If you run into problems doing that, we can provide more targeted advice. If anyone else has a better or more clever idea for how to do this I'd be interested to hear.
Plus de réponses (1)
Luca Ferro le 24 Mai 2023
Modifié(e) : Luca Ferro le 24 Mai 2023
This is the closest i could go as of right now, i'll revise it in the next days. But i'll share it so that someone else can build on it to reach the final solution.
Basically what it does is analyzing the signal flat section per flat section.
[peaks ,peaksIdx]=findpeaks(signal); %find peaks
peaksIdx=[peaksIdx ; inf];
for pp=1:size(peaks,1)-1 %loopsthrough each peak
while ss<peaksIdx(pp+1) && signal(ss)==peaks(pp) && flat(ss)==0
end %detects peak and moves to the end of it
while flat(ss)~=0 && ss<peaksIdx(pp+1)
end %moves to the next flat area
while ss<peaksIdx(pp+1) && flat(ss)==0
if signal(ss)/peaks(pp) > 0.3
end %if the flat area has the proper specifics highlights it
The issue that this has is that it only highlights the first drop and not the following ones.
Disclaimer: is not the best approach, is not the cleanest code. I'll revise the abuse of loops later to find a better structure.