I want to denoise a signal using wavelets.
I have generated an ideal sine wave of two different frequencies and added noise to it.
Please let me know how to denoise the signal "I_as_fft_array_noise" as mentioned in the below code using wavelets.
Import Libraries
from scipy import signal
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.pyplot as plt
import pywt
import sys
Define the signal sine signal of 100Hz and 50Hz
Fs_fft = 1e4 # Sampling Frequency
Pi=np.pi
N1 = (1e5)/2
time1 = np.arange(N1) / float(Fs_fft)
f1 = 100
x1 = 1000*np.sin(2*Pi*f1*time1)
time2 = np.arange(N1,2*N1) / float(Fs_fft)
f2 = 50
x2 = 500*np.sin(2*Pi*f2*time2)
T_fft_array =np.concatenate((time1,time2))
I_as_fft_array = np.concatenate((x1,x2))
Adding noise using target SNR
Reference: adding noise to a signal in python
I_as_fft_array_watts = I_as_fft_array ** 2
I_as_fft_array_db = 10 * np.log10(I_as_fft_array_watts)
target_snr_db = 20
sig_avg_watts = np.mean(I_as_fft_array_watts)
sig_avg_db = 10 * np.log10(sig_avg_watts)
noise_avg_db = sig_avg_db - target_snr_db
noise_avg_watts = 10 ** (noise_avg_db / 10)
mean_noise = 0
noise_volts = np.random.normal(mean_noise, np.sqrt(noise_avg_watts), len(I_as_fft_array_watts))
I_as_fft_array_noise = I_as_fft_array + noise_volts
Plot ideal signal
plt.plot(T_fft_array , I_as_fft_array)
plt.title('Ideal Signal')
plt.ylabel('Current [A]')
plt.xlabel('Time [sec]')
plt.show()
Plot signal with noise
plt.plot(T_fft_array, I_as_fft_array_noise)
plt.title('Signal with noise')
plt.ylabel('Voltage (V)')
plt.xlabel('Time (s)')
plt.show()
Related
I try do a wavelet transform on a signal.
The signal is recorded with 500 Hz (: 500 datapoints per second). I just want to do a wavelet transform on 0.2 seconds of the signal (-> 100 datapoints).
I am really not sure how to define parameter "w" and also if the y-axis is scaled correctly? I cannot find anything in the documentation of scipy to "w".
My code and output looks as follows:
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal
t, dt = np.linspace(0, 0.2, 100, retstep=True)
fs = 1/dt
w = 6.
sig = sig[0:100] # 0.2 seconds of the signal
freq = np.linspace(1, fs/2, 100)
widths = w*fs / (2*freq*np.pi)
cwtm = signal.cwt(sig, signal.morlet2, widths, w=w)
plt.pcolormesh(t, freq, np.abs(cwtm), cmap='jet', shading='gouraud')
plt.xlabel("Time")
plt.ylabel("Scale")
plt.show()
Output:
Bonus question: How would you interprete the output in two sentences?
I want to plot a power spectrum from my data set (array of about 2000 values, the data is recorded every minute).
I've gotten so far as:
y= np.fft.fft(data)
abs = np.abs(y) #absolute value
p = np.square(abs) #power
but am confused about setting the frequency.
I've tried using freqs = np.fft.fftfreq(len(y)), but when I plot the result it looks like, which can't be right.
What am I doing wrong?
Here is an example to plot the power spectrum:
import matplotlib.pyplot as plt
import numpy as np
t = np.linspace(0,2000,200)
data = 2 * np.sin(2*np.pi *60*t) + 2 * np.sin(2*np.pi *42*t)
spectrum = np.fft.fft(data)
power_spectrum = np.square(np.abs(spectrum))
fig, ax = plt.subplots()
ax.plot(np.arange(len(power_spectrum)), power_spectrum)
plt.show()
I'm trying to figure out why Mel scale spectrogram seems to have the wrong frequency scale. I generate a 4096Hz tone and plot it using librosa's display library, and the tone does not align with the known frequency? I'm obviously doing something wrong, can someone help? Thanks!
import numpy as np
import librosa.display
import matplotlib.pyplot as plt
sr = 44100
t = np.linspace(0, 1, sr)
y = 0.1 * np.sin(2 * np.pi * 4096 * t)
M = librosa.feature.melspectrogram(y=y, sr=sr)
M_db = librosa.power_to_db(M, ref=np.max)
librosa.display.specshow(M_db, y_axis='mel', x_axis='time')
plt.show()
When you compute the mel spectrogram using librosa.feature.melspectrogram(y=y, sr=sr) you implicitly create a mel filter using the parameters fmin=0 and fmax=sr/2 (see docs here). To correctly plot the spectrogram, librosa.display.specshow needs to know how it was created, i.e. what sample rate sr was used (to get the time axis right) and what frequency range was used to get the frequency axis right. While librosa.feature.melspectrogram defaults to 0 - sr/2, librosa.display.specshow unfortunately defaults to 0 - 11050 (see here). This describes librosa 0.8—I could imagine this changes in the future.
To get this to work correctly, explicitly add fmax parameters. To also get the time axis right, add the sr parameter to librosa.display.specshow:
import numpy as np
import librosa.display
import matplotlib.pyplot as plt
sr = 44100
t = np.linspace(0, 1, sr)
y = 0.1 * np.sin(2 * np.pi * 4096 * t)
M = librosa.feature.melspectrogram(y=y, sr=sr, fmax=sr/2)
M_db = librosa.power_to_db(M, ref=np.max)
librosa.display.specshow(M_db, sr=sr, y_axis='mel', x_axis='time', fmax=sr/2)
plt.show()
I'm creating a sine wave of 100Hz and trying to plot it's stft :
import scipy.io
import numpy as np
import librosa
import librosa.display
#%matplotlib notebook
import matplotlib.pyplot as plt
A = 1 # Amplitude
f0 = 100 # frequency
Fs = f0 * 800 # Sampling frequency
t = np.arange(Fs) / float(Fs)
X = np.sin(2*np.pi*t*f0)
plt.plot(t, X)
plt.xlabel("Time")
plt.ylabel("Amplitude")
plt.show()
D = np.abs(librosa.stft(X))
librosa.display.specshow(librosa.amplitude_to_db(D,ref=np.max),y_axis='log', x_axis='time')
I was expecting a single line at 100Hz instead.
Also, how can I plot Frequency(X-axis) vs Amplitude(Y-axis) graph to see a peak at 100Hz?
You need to pass the sample rate to specshow, using the sr keyword argument. Otherwise it will default to 22kHz, which will give wrong results.
D = np.abs(librosa.stft(X))
db = librosa.amplitude_to_db(D,ref=np.max)
librosa.display.specshow(db, sr=Fs, y_axis='log', x_axis='time')
I'm having trouble with my code. It's only showing the data for one graph and the other graph is blank. I can't figure why it's not working.
I'm using the subplot() function and my guess is that the the reason might be the way my function are formatted.
import numpy as np
import matplotlib.pyplot as plt
import cvxopt as opt
from cvxopt import blas, solvers
import pandas as pd
import mpld3
from mpld3 import plugins
np.random.seed(123)
solvers.options['show_progress'] = False
n_assets = 4
n_obs = 1000 # original 1000
return_vec = np.random.randn(n_assets, n_obs)
def rand_weights(n):
k = np.random.rand(n)
return k / sum(k) print(rand_weights(n_assets)) print(rand_weights(n_assets))
def random_portfolio(returns):
p = np.asmatrix(np.mean(returns,axis=1))
w = np.asmatrix(rand_weights(returns.shape[0]))
C = np.asmatrix(np.cov(returns))
mu = w * p.T
sigma = np.sqrt(w * C * w.T)
#this recursion reduces outlier to keep the graph nice
if sigma > 2:
return random_portfolio(returns)
return mu, sigma
n_portfolios = 500
means, stds = np.column_stack([random_portfolio(return_vec) for _ in range(n_portfolios)])
plt.plot(return_vec.T, alpha=.4);
plt.xlabel('time')
plt.ylabel('returns')
plt.figure(1)
plt.subplot(212)
plt.plot(stds, means, 'o', markersize = 5)
plt.xlabel('std')
plt.ylabel('mean')
plt.title('Mean and standard deviation of returns of randomly generated portfolios')
plt.subplot(211)
plt.figure(1)
plt.show()
You need to move the line plt.subplot(211) before your first call to plt.plot. This is because calls to plt.subplot must precede the actual plotting in that subplot.