diff --git a/src/yapsut/__init__.py b/src/yapsut/__init__.py index ddc8eb0cdb3630b0e4b13c08c83594f9764ddbbc..b8965bab1d40f772a123b013696b959f7ce734e3 100644 --- a/src/yapsut/__init__.py +++ b/src/yapsut/__init__.py @@ -15,6 +15,7 @@ from .geometry import ElipsoidTriangulation from .template_subs import discoverKeys, templateFiller from .periodic_stats import periodic_stats, periodic_centroid from .stats import CumulativeOfData +from .colored_noise import gaussian_colored_noise #from import .grep #import .intervalls diff --git a/src/yapsut/colored_noise.py b/src/yapsut/colored_noise.py new file mode 100644 index 0000000000000000000000000000000000000000..907c72c5eb2fa85cb50064c5c36dbe4a555c224c --- /dev/null +++ b/src/yapsut/colored_noise.py @@ -0,0 +1,126 @@ +""" +Utility to create colored noises in a controlled manner + +Doc: + +https://stackoverflow.com/questions/67085963/generate-colors-of-noise-in-python + +Also look at: + +https://pypi.org/project/colorednoise/ +pip3 colorednoise --user + + +""" + +import numpy as np + +class gaussian_colored_noise : + @property + def N(self) : + """Number of samples generated per chunk""" + return self._N + @property + def wn_mean(self) : + """white noise sigma""" + return self._wn_mean + @property + def wn_sigma(self) : + """white noise sigma""" + return self._wn_sigma + @property + def fknee(self) : + """fknee in units of the fsamp, fknee in [0,0.5]""" + return self._fknee + @property + def alpha(self) : + """alpha spectral index""" + return self._alpha + @property + def freq(self) : + """the frequencies in units of fsamp in the range [0,0.5].""" + return self._freq + @property + def ps_shape(self) : + """the spectral shape: ps_shape=P(f)**0.5""" + return self._S + @property + def seed(self) : + """the seed of the random number generator""" + return self._seed + def __init__(self,N,wn_mean,wn_sigma,fknee,alpha,zero_policy='I',seed=None) : + """ +Creates a gaussian_colored_noise_generator. + +Power spectrum of gaussian colored noise generator is: + + P(f) = (1+ fknee/f)**alpha + +Parameters: +=========== + :N: number of samples to be generated + :wn_mean: white noise mean + :wn_sigma: white noise rms + :fknee: knee frequency + :alpha: power spectral index + +Keywords: +========= + :zero_policy: the policy by which to define P(0) + valid policies are 'M','I', '1', '0','100x1' + '0' : P(0)**0.5=0 + '1' : P(0)**0.5=1 + 'I' : P(0)**0.5 is left as it is + 'M' : P(0)**0.5 = wn_mean + '100x1' : P(0)**0.5=(1+100*fknee/freq[1])**alpha/2 + note that zero_policy affects the mean value of the chunck but not its variance + default value is 'I' that for alpha > 0 gives P(0)=1 + + :seed: the seed for the random number generator, if None no seed is applied otherwise the same seed is applied to any generated sequence + """ + self._N=int(N) + self._wn_mean=wn_mean + self._wn_sigma=wn_sigma + self._fknee=fknee + self._alpha=alpha + self._seed=seed + # + if str(zero_policy) in ['0','1','M','I','100x1'] : + self._zero_policy = str(zero_policy) + else : + raise Error("Error: invalid zero policy, valid values: '0','1','M','I','100x1'") + # + self._freq=np.fft.rfftfreq(self.N) + # + pl=self.alpha/2 + with np.errstate(divide='ignore'): + x=self.fknee/np.where(self._freq==0, np.inf , self._freq) + self._S=(1+x)**pl + # + if self._zero_policy=='0' : + self._S[0]=0. + elif self._zero_policy=='1' : + self._S[0]=1. + elif self._zero_policy=='M' : + self._S[0]=self.wn_mean + elif self._zero_policy=='100x1' : + self._S[0]=1 if fknee>ff[1] else (1+100*self.fknee/self._freq[1])**pl + else : # self._zero_policy=='I' : + # left things as they are + pass + # + def __call__(self,OutAll=False) : + """computes the colored noise, if OutAll == False returns just the cn if True returns + (colored_noise,white_noise,colored_noise_rfft, colored_noise_shape, white_noise_rfft, original_white_noise) + """ + if not self.seed is None : np.random.seed(self.seed) + # + # + x_w=self.wn_sigma*np.random.randn(self.N)+self.wn_mean + X_white=np.fft.rfft(x_w); + X_shaped=self._S*X_white + cn=np.fft.irfft(X_shaped) + if OutAll==False : return cn + wn=np.fft.irfft(X_white) + return cn,wn,X_shaped,X_white,x_w +