A picture is worth a thousand words (sorry for the shoddy work):
If the solution is preserving the value and the slope at both ends it is better. If, in addition, the position and sharpness of the transition can be adjusted it is perfect.
But I have not found any solution yet…
Thank you very much for your help
Here is a piece of code to get started:
import matplotlib.pyplot as plt from scipy.signal import savgol_filter import numpy as np def round_up_to_odd(f): return np.int(np.ceil(f / 2.) * 2 + 1) def generateRandomSignal(n=1000, seed=None): """ Parameters ---------- n : integer, optional Number of points in the signal. The default is 1000. Returns ------- sig : numpy array """ np.random.seed(seed) print("Seed was:", seed) steps = np.random.choice(a=[-1, 0, 1], size=(n-1)) roughSig = np.concatenate([np.array([0]), steps]).cumsum(0) sig = savgol_filter(roughSig, round_up_to_odd(n/20), 6) return sig n = 1000 t = np.linspace(0,10,n) seed = np.random.randint(0,high=100000) #seed = 45136 sig = generateRandomSignal(seed=seed) ############################### # ???? # sigFilt = adaptiveFilter(sig) ############################### # Plot plt.figure() plt.plot(t, sig, label="Signal") # plt.plot(t, sigFilt, label="Signal filtered") plt.legend()
Advertisement
Answer
Simple convolution does smoothing. However, as mentioned below, here we need strong smoothing first and no smoothing towards the end. I used the moving average approach with the dynamic size of the window. In the example below, the window size changes linearly.
def dynamic_smoothing(x, start_window_length=(len(x)//2), end_window_length=1): d_sum = np.cumsum(a, dtype=float) smoothed = list() for i in range(len(x)): # compute window length a = i / len(x) w = int(np.round(a * start_window_length + (1.0-a) * end_window_length)) # get the window w0 = max(0, i - w) # the window must stay inside the array w1 = min(len(x), i + w) smoothed.append(sum(x[w0:w1])/(w1+w0)) return np.array(smoothed)