In [1]:
    
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
    
Here are gathered methods for generating random signals and also some comparison factors.
In [2]:
    
# Time series, that we will use for examples
t = np.linspace(0, 10, 2**15)
dt = t[1]
    
In [3]:
    
def pure_random(t, mean=0, σ=1/np.sqrt(2)):
    """
    Uses normal distribution; uses a simple random number generator.
    
    Values are distributed normally, parameters:
    t       - time series
    mean    - mean (expected) value
    σ       - standard deviation of the gaussian distribution
    
    """
    
    N = t.size
    r = np.random.normal(mean, scale=σ, size=N)
    
    return r
    
In [4]:
    
r_pure_random = pure_random(t)
    
In [5]:
    
R_pure_random = np.fft.rfft(r_pure_random)
f_pure_random = np.fft.rfftfreq(r_pure_random.size, d=dt)
    
In [6]:
    
fig, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(15,4))
fig.suptitle("Pure Random", fontsize=16)
fig.subplots_adjust(wspace=0.3)
ax1.plot(t, r_pure_random)
ax1.set_xlabel('t [s]')
ax1.set_ylabel('r')
ax2.plot(f_pure_random, np.abs(R_pure_random)/R_pure_random.size)
ax2.set_xlabel('f [1/s]')
ax2.set_ylabel('Amplitude')
ax3.plot(f_pure_random, np.angle(R_pure_random))
ax3.set_xlabel('f [1/s]')
ax3.set_ylabel('Phase')
#plt.savefig('pure_random')
    
    Out[6]:
    
Generation time
In [7]:
    
%%timeit
pure_random(t)
    
    
Energy spectral density
In [8]:
    
E_pure_random = t[-1]*np.sum(r_pure_random**2)
E_pure_random
    
    Out[8]:
Power spectral density
In [9]:
    
P_pure_random = 1/len(t)*np.sum(r_pure_random**2)
P_pure_random
    
    Out[9]:
RMS value (Root Mean Square)
In [10]:
    
RMS_pure_random = np.sqrt(P_pure_random)
RMS_pure_random
    
    Out[10]:
Crest factor
In [11]:
    
c_pure_random = np.max(np.abs(r_pure_random))/RMS_pure_random
c_pure_random
    
    Out[11]:
In [58]:
    
def pseudo_random(t, repeats, A):
    """
    Uniform distribution for phases.
    
    Parameters:
    t       - time series, length = n*repeats, repeats is an integer
    repeats - number of repeats of a time block
    A       - desired amplitudes, length = n//2 + 1
    """
    n = len(t)//repeats
    a = A*(n//2 + 1)
    R = a*np.exp(1j*np.random.uniform(0,2*np.pi,n//2 + 1))
    
    r0 = np.fft.irfft(R) # one block
    r = np.tile(r0, repeats) # N blocks
    
    return r
    
In [59]:
    
repeats = 8
n = t.size//repeats
A = np.ones(n//2 +1)
    
In [60]:
    
r_pseudo_random = pseudo_random(t, repeats, A)
    
In [61]:
    
n_1 = t.size
A_1 = np.ones(n_1//2 +1)
r_pseudo_random_1 = pseudo_random(t, 1, A_1)
    
In [62]:
    
R_pseudo_random = np.fft.rfft(r_pseudo_random[:(r_pseudo_random.size/repeats)])
f_pseudo_random = np.fft.rfftfreq(r_pseudo_random[:(r_pseudo_random.size/repeats)].size, d=dt)
    
    
In [63]:
    
fig, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(15,4))
fig.suptitle("Pseudo Random", fontsize=16)
fig.subplots_adjust(wspace=0.3)
ax1.plot(t, r_pseudo_random)
ax1.set_xlabel('t [s]')
ax1.set_ylabel('r')
ax2.plot(f_pseudo_random, np.abs(R_pseudo_random)/R_pseudo_random.size)
ax2.set_xlabel('f [1/s]')
ax2.set_ylabel('Amplitude')
ax3.plot(f_pseudo_random, np.angle(R_pseudo_random))
ax3.set_xlabel('f [1/s]')
ax3.set_ylabel('Phase')
#plt.savefig('pure_random')
    
    Out[63]:
    
Generation time for 8 repeats
In [18]:
    
%%timeit
pseudo_random(t, repeats, A)
    
    
Generation time for 1 repeat
In [19]:
    
%%timeit
pseudo_random(t, 1, A_1)
    
    
Scaling factor
In [20]:
    
SF1 = max(abs(r_pure_random))
SF2 = max(abs(r_pseudo_random))
SF = SF1/SF2
r_pseudo_random = r_pseudo_random*SF
    
Energy spectral density
In [21]:
    
E_pseudo_random = t[-1]*np.sum(r_pseudo_random**2)
E_pseudo_random
    
    Out[21]:
Power spectral density
In [22]:
    
P_pseudo_random = 1/len(t)*np.sum(r_pseudo_random**2)
P_pseudo_random
    
    Out[22]:
RMS value (Root Mean Square)
In [23]:
    
RMS_pseudo_random = np.sqrt(P_pseudo_random)
RMS_pseudo_random
    
    Out[23]:
Crest factor
In [24]:
    
c_pseudo_random = np.max(np.abs(r_pseudo_random))/RMS_pseudo_random
c_pseudo_random
    
    Out[24]:
In [25]:
    
def periodic_random(t, repeat_sequence, mean=0, σ=1/np.sqrt(2)):
    """
    Uses normal distribution; uses a simple random number generator.
    
    Values are distributed normally, parameters:
    t               - time series
    mean            - mean (expected) value
    σ               - standard deviation of the gaussian distribution
    repeat_sequence - repeat sequence of different time blocks i.e. (AABBCC),
                      where A, B and C are different time blocks with the same time length;
                      example [1, 3, 2] denotes (ABBBCC)
    
    """
    
    r = np.array([])
    
    N = t.size//(sum(repeat_sequence))
    
    for i in repeat_sequence:
        r0 = np.random.normal(mean, scale=σ, size=N)
        r1 = np.tile(r0, i)
        r = np.append(r, r1)
    
    return r
    
In [26]:
    
repeat_sequence = [8,8]
    
In [27]:
    
r_periodic_random = periodic_random(t, repeat_sequence)
    
In [28]:
    
repeat_sequence_1 = [1]
r_periodic_random_1 = periodic_random(t, repeat_sequence_1)
    
In [29]:
    
R_periodic_random = np.fft.rfft(r_periodic_random[:(r_periodic_random.size//sum(repeat_sequence))])
f_periodic_random = np.fft.rfftfreq(r_periodic_random[:(r_periodic_random.size//sum(repeat_sequence))].size, d=dt)
    
In [30]:
    
fig, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(15,4))
fig.suptitle("Periodic Random", fontsize=16)
fig.subplots_adjust(wspace=0.3)
ax1.plot(t, r_periodic_random)
ax1.set_xlabel('t [s]')
ax1.set_ylabel('r')
ax2.plot(f_periodic_random, np.abs(R_periodic_random)/R_periodic_random.size)
ax2.set_xlabel('f [1/s]')
ax2.set_ylabel('Amplitude')
ax3.plot(f_periodic_random, np.angle(R_periodic_random))
ax3.set_xlabel('f [1/s]')
ax3.set_ylabel('Phase')
#plt.savefig('pure_random')
    
    Out[30]:
    
Generation time for 8+8 repeats
In [31]:
    
%%timeit
periodic_random(t, repeat_sequence)
    
    
Generation time for 1 repeat
In [32]:
    
%%timeit
periodic_random(t, repeat_sequence_1)
    
    
Energy spectral density
In [33]:
    
E_periodic_random = t[-1]*np.sum(r_periodic_random**2)
E_periodic_random
    
    Out[33]:
Power spectral density
In [34]:
    
P_periodic_random = 1/len(t)*np.sum(r_periodic_random**2)
P_periodic_random
    
    Out[34]:
RMS value (Root Mean Square)
In [35]:
    
RMS_periodic_random = np.sqrt(P_periodic_random)
RMS_periodic_random
    
    Out[35]:
Crest factor
In [36]:
    
c_periodic_random = np.max(np.abs(r_periodic_random))/RMS_periodic_random
c_periodic_random
    
    Out[36]: