├── .gitattributes ├── .gitignore ├── README.md └── makesomenoise.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | __pycache__/makesomenoise.cpython-38.pyc 3 | .ipynb_checkpoints/make-some-noise-checkpoint.ipynb 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Make some noise! 2 | By André van Schaik, \ 3 | International Centre for Neuromorphic Systems, \ 4 | Western Sydney University, \ 5 | January 2021\ 6 | \ 7 | This notebook shows how to generate noise with a user defined distribution AND a user defined autocorrelation. 8 | -------------------------------------------------------------------------------- /makesomenoise.py: -------------------------------------------------------------------------------- 1 | 2 | def makesomenoise(xi, acf, fs): 3 | ''' 4 | Produces noise with a specified autocorrelation function 5 | 6 | Parameters: 7 | 8 | xi - input noise sequence 9 | acf - desired autocorrelation of the noise as a numpy array 10 | fs. - sample frequency of the autocorrelation and the noise 11 | 12 | Returns: 13 | xo - reordered version of xi to produce the desired acf 14 | ''' 15 | 16 | import numpy as np 17 | 18 | N = xi.shape[0] # Get number of samples 19 | psd = np.fft.fft(acf, N) # Calculate PSD (Power Spectral Density) from ACF 20 | psd[0] = 0 # Zero out the DC component (remove mean) 21 | 22 | Af = np.sqrt(2 * np.pi * fs * N * psd) # Convert PSD to Fourier amplitudes 23 | mx = np.mean(xi) # Calculate mean of samples 24 | x = xi - mx # Make zero mean 25 | xs = np.sort(x) # Store sorted signal xs with correct PDF 26 | k = 1 27 | idxr = np.zeros(N) # Reference index array 28 | while(k != 0): 29 | Fx = np.fft.fft(x) # Compute FT of noise 30 | Px = np.arctan2(np.imag(Fx), np.real(Fx)) # Get phases 31 | # Create a signal with correct PSD and original phases 32 | xg = np.real(np.fft.ifft((np.exp(1.j*Px)) * np.abs(Af))) 33 | idx = np.argsort(xg) # Get rank indices of signal with correct PSD 34 | x[idx] = xs # Put original noise samples in desired rank order. 35 | k = k+1 # Increment counter 36 | if (idx == idxr).all() : 37 | print(f'Number of iterations = {k}') 38 | k = 0 # If we converged, stop 39 | else: 40 | if k%500 == 0: print(f'Number of iterations = {k} ...') 41 | idxr = idx # Re-set ordering for next iter 42 | x = x + mx # Restore the original mean 43 | return(x) 44 | 45 | 46 | 47 | 48 | 49 | def plot_noise(xi, xo, pdf, acf, fs, range1): 50 | ''' 51 | Helper function to plot the output noise and targets. 52 | ''' 53 | 54 | import matplotlib.pyplot as plt 55 | import numpy as np 56 | 57 | if 'fig' in locals(): 58 | plt.close(fig) 59 | fig = plt.figure(figsize = (8, 8)) 60 | 61 | dt = 1/fs 62 | N = xi.size 63 | M = acf.size - 1 64 | 65 | ax1 = plt.subplot(2,1,1) 66 | if xi.size>1000: 67 | time = np.arange(1000)*dt 68 | ax1.plot(time, xi[:1000], 'C0', label='input') 69 | ax1.plot(time, xo[:1000], 'C1', label='output') 70 | else: 71 | time = np.arange(xi.size)*dt 72 | ax1.plot(time, xi, 'C0', label='input') 73 | ax1.plot(time, xo, 'C1', label='output') 74 | ax1.legend() 75 | ax1.set_xlabel('time (s)') 76 | ax1.set_title('noise sequency') 77 | 78 | ax2 = plt.subplot(2,2,3) 79 | ax2.hist(xo, bins=range1, density=True, color='C0', label='output') 80 | ax2.plot(range1, pdf, color='C1', linestyle='--', label='target') 81 | ax2.hist(xi, bins=range1, density=True, label='input', color='C3', alpha=0.2) 82 | ax2.legend() 83 | ax2.set_xlabel('amplitude (AU)') 84 | ax2.set_title('pdf') 85 | 86 | ax3 = plt.subplot(2,2,4) 87 | range2 = int(M/2) 88 | lags = np.linspace(-range2-1,range2,2*range2+1) 89 | xcor = np.correlate(xo, xo, mode='full')/N 90 | xcor = xcor/xcor.max() 91 | ax3.plot(lags*dt, xcor[N-range2-1:N+range2], color='C0', label='output') 92 | ax3.plot(lags*dt, acf, color='C1', linestyle='--', label='target') 93 | ax3.legend() 94 | ax3.set_xlabel('lag (s)') 95 | ax3.set_title('acf') --------------------------------------------------------------------------------