Search code examples
pythonsignalssignal-processingdata-analysisdata-cleaning

How to remove constant part of a signal in python?


I have a dataset where it is constant sometimes with small noise. It can be on the top, it can be in the middle. I want to remove all constant part of the signal so that it compress into a smaller length.

Lets say if 200 consicutive value is same (or in a threshold limit to be considered as constant) then consider that part as constant .

Any solution code or logical suggestion will be appriciated. Thanks for your time.

I have attached a sample data google drive link in .npy format.

In the below sample image I have indicated (red) which part I want to get rid of as an example:

enter image description here


Solution

  • I came up with the following solution. The answer from @rsenne helped me to start but that was not the solution I have wanted. Please let me know if there anything I should add in my solution to improve the performance.

    import numpy as np
    
    def remove_flat_segments(data, threshold, min_length):
           
           """
           Remove flat segments from data within a threshold and with a minimum length.
        
           Parameters:
            data (ndarray): Input data array.
            threshold (float): Threshold for flatness.
            min_length (int): Minimum length of flat segment to be removed.
        
           Returns:
            ndarray: Data with flat segments removed.
           """
        flat_segments = []
        start_idx = None
        
        for i in range(len(data)):
            if start_idx is None:
                start_idx = i
            elif abs(data[i] - data[i-1]) > threshold:
                if i - start_idx >= min_length:
                    flat_segments.append((start_idx, i-1))
                start_idx = None
        
        if start_idx is not None and len(data) - start_idx >= min_length:
            flat_segments.append((start_idx, len(data)-1))
        
        if len(flat_segments) > 0:
            flat_indices = np.concatenate([np.arange(start, end+1) for start, end in flat_segments])
            return np.delete(data, flat_indices)
        else:
            return data
    
    
    threshold = 0.01
    min_length = 1000
    
    filtered_data = remove_flat_segments(data, threshold, min_length)
    

    The resulted image looks like: enter image description here