1

My ultimate goal is to get the starting point of pulses. They are firing kick and reflection kick(very small in the right hand side).

Currently I need to manually crop them and feed the signal to my program in order to determine the starting points.

Update: With logic level applied to my signal. I got this Blue is logic level. Orange is signal. Logic level

Question:

How to crop the firing kick and reflection kick signal?

I have tried searching with anomaly detection, 1D edge detection. But not found my answers.

Transducer signal

joe
  • 8,383
  • 13
  • 61
  • 109
  • Have you tried a digital threshold value? (maybe a low-pass filter?) – Neil Mar 25 '22 at 03:56
  • What does it mean? – joe Mar 25 '22 at 04:00
  • 1
    Like [logic levels](https://en.wikipedia.org/wiki/Logic_level); say, anything greater than 0.5 is 1, less is 0. I don't know whether you are trying to extract more then one signal, though. – Neil Mar 25 '22 at 04:04
  • Is this a timing signal? – Neil Mar 25 '22 at 04:26
  • Yes, it is millisecond vs mV – joe Mar 25 '22 at 04:28
  • Update: is the signal at 10.0ms noise? It looks like you have to increase the threshold (both +/-) to get a clear signal. Usually, the timing signal only needs two levels, say -0.5V? – Neil Mar 25 '22 at 04:49

1 Answers1

1

Thanks to Neil for logic level hinting. I can find the starting points of my signal.

  1. Apply logic level to the signal.
import pandas as pd
from scipy.ndimage import gaussian_filter1d


def logic_level_gaussian(signal_y: pd.Series, size:int=10) -> typ.List[float]:
    """Visualize logic level and apply gaussian filter to smooth the signal."""
    logic_level_y = []

    for _ in gaussian_filter1d(signal_y, 10):
        if total_mean + 0.05 * total_sd < _:
            logic_level_y.append(1)
        elif _ < total_mean - 0.05 * total_sd:
            logic_level_y.append(-1)
        else:
            logic_level_y.append(0)
    plt.plot(logic_level_y)
    plt.plot(signal_y)
    return logic_level_y

  1. logic_50 = logic_level_gaussian(y, 50) The logic level result. enter image description here

  2. Find my down kick and put them into array

down_kick_time_array = []

for my_time, my_y in zip(x, logic_50):
    # Find down kick
    if my_y < 0:
        down_kick_time_array.append(my_time)

enter image description here

  1. Cluster them using cluster() from here
logic_level_groups = cluster(down_kick_time_array, maxgap=1)
  1. Now I can identify starting point of firing kick and reflecting kick. They are
for _ in logic_level_groups:
    print(f"Starting point of this cluster is: {_[0]}")

Starting point of this cluster is: 1.471
Starting point of this cluster is: 2.651
Starting point of this cluster is: 10.205

Therefore

logic_level_groups[-1][0] - logic_level_groups[0][0]
8.734

The time between firing kick and reflecting kick is 8.734 ms

joe
  • 8,383
  • 13
  • 61
  • 109
  • What if you do `if _ < -0.5 then logic_level_y.append(1) else logic_level_y.append(0)`, and then pick the rising edge every time? – Neil Mar 26 '22 at 18:43
  • It pick nothing. – joe Mar 28 '22 at 01:24
  • That is interesting; with this, I would expect that for `for _ in signal_y` of -0.5 (V?) or lower, would be one. Usually a timing signal is specifically designed to be easily picked up. I've never worked with logic in python; I would think this might be done easier, but glad you have found a way that works. – Neil Mar 28 '22 at 22:04