Example #1
0
    def compute(self, waveforms, window_length, increment, samplerate=16000, min_freq=0, max_freq=None, nstd=6, offset=50):

        signal, stimulus = waveforms

        self.time, self.frequencies, spec = gaussian_stft(signal,
                                                          samplerate,
                                                          window_length,
                                                          increment,
                                                          min_freq=min_freq,
                                                          max_freq=max_freq,
                                                          nstd=nstd)[:3]
        stim_spec = gaussian_stft(stimulus,
                                  samplerate,
                                  window_length,
                                  increment,
                                  min_freq=min_freq,
                                  max_freq=max_freq,
                                  nstd=nstd)[2]

        ratio_mask = np.abs(spec) ** self.alpha / np.abs(stim_spec) ** self.alpha
        ratio_mask = np.maximum(0, np.minimum(1, ratio_mask)).T
        stim_spec = log_spectrogram(np.abs(stim_spec), offset=offset).T
        self.mean = np.mean(stim_spec, axis=0)
        stim_spec -= self.mean

        return stim_spec, ratio_mask
Example #2
0
def cross_spectral_density(s1, s2, sample_rate, window_length, increment, min_freq=0, max_freq=np.inf):
    """ Computes the cross-spectral density between signals s1 and s2 by computing the product of their power spectra.
        First the Gaussian-windowed spectrograms of s1 and s2 are computed, then the product of the power spectra
        at each time point is computed, then the products are averaged across time to produce an estimate of the
        cross spectral density.

    :param s1: The first signal.
    :param s2: The second signal.
    :param sample_rate: The sample rates of the signals.
    :param window_length: The length of the window used to compute the STFT (units=seconds)
    :param increment: The spacing between the points of the STFT  (units=seconds)
    :param min_freq: The minimum frequency to analyze (units=Hz, default=0)
    :param max_freq: The maximum frequency to analysize (units=Hz, default=nyquist frequency)

    :return: freq,csd: The frequency bands evaluated, and the cross-spectral density.
    """

    # compute the complex-spectrograms of the signals
    t1, freq1, tf1, rms1 = gaussian_stft(s1, sample_rate, window_length=window_length, increment=increment,
                                         min_freq=min_freq, max_freq=max_freq)

    t2, freq2, tf2, rms2 = gaussian_stft(s2, sample_rate, window_length=window_length, increment=increment,
                                         min_freq=min_freq, max_freq=max_freq)

    # multiply the complex spectrograms
    csd = tf1*tf2

    # take the power spectrum
    csd = np.abs(csd)

    # average across time
    csd = csd.mean(axis=1)

    return freq1,csd
Example #3
0
def cross_spectral_density(s1,
                           s2,
                           sample_rate,
                           window_length,
                           increment,
                           min_freq=0,
                           max_freq=np.inf):
    """ Computes the cross-spectral density between signals s1 and s2 by computing the product of their power spectra.
        First the Gaussian-windowed spectrograms of s1 and s2 are computed, then the product of the power spectra
        at each time point is computed, then the products are averaged across time to produce an estimate of the
        cross spectral density.

    :param s1: The first signal.
    :param s2: The second signal.
    :param sample_rate: The sample rates of the signals.
    :param window_length: The length of the window used to compute the STFT (units=seconds)
    :param increment: The spacing between the points of the STFT  (units=seconds)
    :param min_freq: The minimum frequency to analyze (units=Hz, default=0)
    :param max_freq: The maximum frequency to analysize (units=Hz, default=nyquist frequency)

    :return: freq,csd: The frequency bands evaluated, and the cross-spectral density.
    """

    # compute the complex-spectrograms of the signals
    t1, freq1, tf1, rms1 = gaussian_stft(s1,
                                         sample_rate,
                                         window_length=window_length,
                                         increment=increment,
                                         min_freq=min_freq,
                                         max_freq=max_freq)

    t2, freq2, tf2, rms2 = gaussian_stft(s2,
                                         sample_rate,
                                         window_length=window_length,
                                         increment=increment,
                                         min_freq=min_freq,
                                         max_freq=max_freq)

    # multiply the complex spectrograms
    csd = tf1 * tf2

    # take the power spectrum
    csd = np.abs(csd)

    # average across time
    csd = csd.mean(axis=1)

    return freq1, csd
Example #4
0
def spectrogram(s, sample_rate, spec_sample_rate, freq_spacing, min_freq=0, max_freq=None, nstd=6, log=True, noise_level_db=80, rectify=True, cmplx = True):
    """
        Given a sound pressure waveform, compute the log spectrogram. See documentation on gaussian_stft for arguments and return values.

        log: whether or not to take the log of th power and convert to decibels, defaults to True
        noise_level_db: the threshold noise level in decibels, anything below this is set to zero. unused of log=False
    """

    increment = 1.0 / spec_sample_rate
    window_length = nstd / (2.0*np.pi*freq_spacing)
    t,freq,timefreq,rms = gaussian_stft(s, sample_rate, window_length, increment, nstd=nstd, min_freq=min_freq, max_freq=max_freq)

    if cmplx:
        return t, freq, timefreq, rms

    if log:
        #create log spectrogram (power in decibels)
        abstimefreq = np.abs(timefreq)
        maxabs = np.max(abstimefreq)
        spec = 20.0*np.log10(abstimefreq/maxabs) + noise_level_db
        if rectify:
            #rectify spectrogram
            spec[spec < 0.0] = 0.0
    else:
        spec = np.abs(timefreq)

    rms = spec.std(axis=0, ddof=1)
    return t,freq,spec,rms
Example #5
0
def spectrogram(s, sample_rate, spec_sample_rate, freq_spacing, min_freq=0, max_freq=None, nstd=6, log=True, noise_level_db=80, rectify=True, cmplx = True):
    """
        Given a sound pressure waveform, compute the log spectrogram. See documentation on gaussian_stft for arguments and return values.

        log: whether or not to take the log of th power and convert to decibels, defaults to True
        noise_level_db: the threshold noise level in decibels, anything below this is set to zero. unused of log=False
    """

    increment = 1.0 / spec_sample_rate
    window_length = nstd / (2.0*np.pi*freq_spacing)
    t,freq,timefreq,rms = gaussian_stft(s, sample_rate, window_length, increment, nstd=nstd, min_freq=min_freq, max_freq=max_freq)

    if cmplx:
        return t, freq, timefreq, rms

    if log:
        #create log spectrogram (power in decibels)
        abstimefreq = np.abs(timefreq)
        maxabs = np.max(abstimefreq)
        spec = 20.0*np.log10(abstimefreq/maxabs) + noise_level_db
        if rectify:
            #rectify spectrogram
            spec[spec < 0.0] = 0.0
    else:
        spec = np.abs(timefreq)

    rms = spec.std(axis=0, ddof=1)
    return t,freq,spec,rms
Example #6
0
    def test_delta(self):

        dur = 30.
        sample_rate = 1e3
        nt = int(dur * sample_rate)
        t = np.arange(nt) / sample_rate
        freqs = np.linspace(0.5, 1.5, nt)
        # freqs = np.ones_like(t)*2.
        s = np.sin(2 * np.pi * freqs * t)

        center_freqs = np.arange(0.5, 4.5, 0.5)

        psi = lambda _t, _f, _bw: (np.pi * _bw**2)**(-0.5) * np.exp(
            2 * np.pi * complex(0, 1) * _f * _t) * np.exp(-_t**2 / _bw**2)
        """
        scalogram = np.zeros([len(center_freqs), nt])
        bandwidth = 1.
        nstd = 6
        nwt = int(bandwidth*nstd*sample_rate)
        wt = np.arange(nwt) / sample_rate

        for k,f in enumerate(center_freqs):
            w = psi(wt, f, bandwidth)
            scalogram[k, :] = convolve1d(s, w)
        """

        win_len = 2.
        spec_t, spec_freq, spec, spec_rms = gaussian_stft(
            s, sample_rate, win_len, 100e-3)

        fi = (spec_freq < 10) & (spec_freq > 0)

        plt.figure()
        gs = plt.GridSpec(100, 1)
        ax = plt.subplot(gs[:30, 0])
        plt.plot(t, s, 'k-', linewidth=4.0, alpha=0.7)

        wa = WaveletAnalysis(s, dt=1. / sample_rate, frequency=True)

        ax = plt.subplot(gs[35:, 0])
        power = wa.wavelet_power
        scales = wa.scales
        t = wa.time
        T, S = np.meshgrid(t, scales)
        # ax.contourf(T, S, power, 100)
        # ax.set_yscale('log')
        # plt.imshow(np.abs(scalogram)**2, interpolation='nearest', aspect='auto', cmap=plt.cm.afmhot_r, origin='lower',
        #            extent=[t.min(), t.max(), min(center_freqs), max(center_freqs)])
        plot_spectrogram(spec_t,
                         spec_freq[fi],
                         np.abs(spec[fi, :])**2,
                         ax=ax,
                         colorbar=False,
                         colormap=plt.cm.afmhot_r)
        plt.plot(t, freqs, 'k-', alpha=0.7, linewidth=4.0)
        plt.axis('tight')
        plt.show()
Example #7
0
    def compute(self, waveform, window_length, increment, samplerate=16000,
                min_freq=0, max_freq=None, nstd=6, offset=50):

        self.time, self.frequencies, spec = gaussian_stft(waveform,
                                                          samplerate,
                                                          window_length,
                                                          increment,
                                                          min_freq=min_freq,
                                                          max_freq=max_freq,
                                                          nstd=nstd)[:3]
        return log_spectrogram(np.abs(spec), offset=offset).T
Example #8
0
def get_syllable_props(agg, stim_id, syllable_order, data_dir):

    wave_pad = 20e-3
    i = (agg.df.stim_id == stim_id) & (agg.df.syllable_order == syllable_order)
    bird = agg.df[i].bird.values[0]
    start_time = agg.df[i].start_time.values[0] - wave_pad
    end_time = agg.df[i].end_time.values[0] + wave_pad
    xindex = agg.df[i].xindex.values[0]
    aprops = {aprop: agg.Xraw[xindex, k] for k, aprop in enumerate(USED_ACOUSTIC_PROPS)}
    aprops['start_time'] = start_time
    aprops['end_time'] = end_time

    duration = end_time - start_time
    sfile = os.path.join(data_dir, bird, 'stims.h5')

    # get the raw sound pressure waveform
    sound_manager = SoundManager(HDF5Store, sfile, read_only=True, db_args={'read_only': True})
    wave = sound_manager.reconstruct(stim_id)

    wave_sr = wave.samplerate
    wave = np.array(wave).squeeze()

    wave /= np.abs(wave).max()
    wave *= aprops['maxAmp']

    wave_t = np.arange(len(wave)) / wave_sr
    wave_si = np.min(np.where(wave_t >= start_time)[0])
    wave_ei = wave_si + int(duration * wave_sr)
    amp_env = temporal_envelope(wave, wave_sr, cutoff_freq=200.0)
    amp_env /= amp_env.max()
    amp_env *= wave.max()

    # compute the spectrogram
    spec_sr = 1000.
    spec_t, spec_freq, spec, spec_rms = gaussian_stft(wave, float(wave_sr), 0.007, 1. / spec_sr, min_freq=300.,
                                                      max_freq=8000.)
    spec = np.abs(spec) ** 2
    log_transform(spec, dbnoise=70)
    spec_si = np.min(np.where(spec_t >= start_time)[0])
    spec_ei = spec_si + int(duration * spec_sr)

    # compute power spectrum
    ps_freq, ps = power_spectrum(wave[wave_si:wave_ei], wave_sr, log=False, hanning=False)

    return {'wave_t':wave_t, 'wave':wave, 'wave_si':wave_si, 'wave_ei':wave_ei, 
            'ps_freq':ps_freq, 'ps':ps, 'amp_env':amp_env,
            'spec_t':spec_t, 'spec_freq':spec_freq, 'spec':spec, 'spec_si':spec_si, 'spec_ei':spec_ei,
            'spec_sample_rate':spec_sr, 'aprops':aprops
            }
Example #9
0
import matplotlib.pyplot as plt
from scipy.io.wavfile import read
import numpy as np
from lasp.timefreq import gaussian_stft
from lasp.sound import plot_spectrogram
import pdb

fname = 'DCCalls16x16/fbird8call1.wav'
wf = read(fname, 'r')[1]

# Frames: 30870.00d, Rate: 44100.00

wl = 0.007  # 7ms
ic = 0.001  # 1ms

t, freq, timefreq, rms = gaussian_stft(wf, 44100, wl, ic)

spec = np.abs(timefreq)
spec = spec / spec.max()
nz = spec > 0
spec[nz] = 20 * np.log10(spec[nz]) + 50
spec[spec < 0] = 0

plot_spectrogram(t, freq, spec)
plt.show()
Example #10
0
def coherence_jn(s1, s2, sample_rate, window_length, increment, min_freq=0, max_freq=None, return_coherency=False):
    """ Computes the coherence between two signals by averaging across time-frequency representations
        created using a Gaussian-windowed Short-time Fourier Transform. Uses jacknifing to estimate
        the variance of the coherence.

    :param s1: The first signal
    :param s2: The second signal
    :param sample_rate: The sample rates of the signals.
    :param window_length: The length of the window used to compute the STFT (units=seconds)
    :param increment: The spacing between the points of the STFT  (units=seconds)
    :param min_freq: The minimum frequency to analyze (units=Hz, default=0)
    :param max_freq: The maximum frequency to analyze (units=Hz, default=nyquist frequency)
    :param return_coherency: Whether or not to return the time domain coherency (default=False)

    :return: freq,coherence,coherence_var,phase_coherence,phase_coherence_var,[coherency,coherency_t]: freq is an array
             of frequencies that the coherence was computed at. coherence is an array of length len(freq) that contains
             the coherence at each frequency. coherence_var is the variance of the coherence. phase_coherence is the
             average cosine phase difference at each frequency, and phase_coherence_var is the variance of that measure.
             coherency is only returned if return_coherency=True, it is the inverse fourier transform of the complex-
             valued coherency.
    """

    t1, freq1, tf1, rms1 = gaussian_stft(s1, sample_rate, window_length=window_length, increment=increment,
                                         min_freq=min_freq, max_freq=max_freq)

    t2, freq2, tf2, rms2 = gaussian_stft(s2, sample_rate, window_length=window_length, increment=increment,
                                         min_freq=min_freq, max_freq=max_freq)

    cross_spec12 = tf1*np.conj(tf2)
    ps1 = np.abs(tf1)**2
    ps2 = np.abs(tf2)**2
    
    # compute the coherence using all the data
    csd = cross_spec12.sum(axis=1)
    denom = ps1.sum(axis=1)*ps2.sum(axis=1)
    c_amp = np.abs(csd) / np.sqrt(denom)
    cohe = c_amp**2

    # compute the phase coherence using all the data
    c_phase = np.cos(np.angle(csd))

    # make leave-one-out estimates of the complex coherence
    jn_estimates_amp = list()
    jn_estimates_phase = list()
    jn_estimates_cohe = list()
    
    njn = tf1.shape[1]
    for k in range(njn):
        i = np.ones([njn], dtype='bool')
        i[k] = False
        csd = cross_spec12[:, i].sum(axis=1)
        denom = ps1[:, i].sum(axis=1)*ps2[:, i].sum(axis=1)
        c_amp = np.abs(csd) / np.sqrt(denom)
        jn_estimates_amp.append(c_amp)
        jn_estimates_cohe.append(njn*cohe - (njn-1)*(c_amp**2))

        c_phase = np.cos(np.angle(csd))
        jn_estimates_phase.append(c_phase)
        

    jn_estimates_amp = np.array(jn_estimates_amp)
    jn_estimates_cohe = np.array(jn_estimates_cohe)
    jn_estimates_phase = np.array(jn_estimates_phase)

    # estimate the variance of the coherence
    jn_mean_amp = jn_estimates_amp.mean(axis=0)
    jn_diff_amp = (jn_estimates_amp - jn_mean_amp)**2
    c_var_amp = ((njn-1) / float(njn)) * jn_diff_amp.sum(axis=0)
    cohe_unbiased = jn_estimates_cohe.mean(axis=0)
    cohe_se = jn_estimates_cohe.std(axis=0)/np.sqrt(njn)
    
    
    # estimate the variance of the phase coherence
    jn_mean_phase = jn_estimates_phase.mean(axis=0)
    jn_diff_phase = (jn_estimates_phase - jn_mean_phase)**2
    c_phase_var = ((njn-1) / float(njn)) * jn_diff_phase.sum(axis=0)



    assert c_amp.max() <= 1.0, "c_amp.max()=%f" % c_amp.max()
    assert c_amp.min() >= 0.0, "c_amp.min()=%f" % c_amp.min()
    assert np.sum(np.isnan(c_amp)) == 0, "NaNs in c_amp!"

    if return_coherency:
        # compute the complex-valued coherency
        z = csd / denom

        # make the complex-valued coherency symmetric around zero
        sym_z = np.zeros([len(z)*2 - 1], dtype='complex')
        sym_z[len(z)-1:] = z
        sym_z[:len(z)-1] = (z[1:])[::-1]

        # do an fft shift so the inverse fourier transform works
        sym_z = fftshift(sym_z)

        if len(sym_z) % 2 == 1:
            # shift zero from end of shift_lags to beginning
            sym_z = np.roll(sym_z, 1)

        coherency = ifft(sym_z)
        coherency = fftshift(coherency.real)

        dt = 1. / sample_rate
        hc = (len(coherency) - 1) / 2
        coherency_t = np.arange(-hc, hc+1, 1)*dt

        """
        import matplotlib.pyplot as plt
        plt.figure()
        plt.plot(coherency_t, coherency, 'k-')
        plt.axis('tight')
        plt.show()
        """

        return freq1,c_amp,c_var_amp,c_phase,c_phase_var,coherency,coherency_t, cohe_unbiased, cohe_se
    else:
        return freq1,c_amp,c_var_amp,c_phase,c_phase_var, cohe_unbiased, cohe_se
Example #11
0
import matplotlib.pyplot as plt
from scipy.io.wavfile import read
import numpy as np
from lasp.timefreq import gaussian_stft
from lasp.sound import plot_spectrogram
import pdb

fname = 'DCCalls16x16/fbird8call1.wav'
wf = read(fname,'r')[1]

# Frames: 30870.00d, Rate: 44100.00

wl = 0.007 # 7ms
ic = 0.001 # 1ms

t,freq,timefreq,rms = gaussian_stft(wf, 44100, wl, ic)

spec = np.abs(timefreq)
spec = spec/spec.max()
nz = spec > 0
spec[nz] = 20*np.log10(spec[nz]) + 50
spec[spec < 0] = 0

plot_spectrogram(t, freq, spec)
plt.show()
Example #12
0
def coherence_jn(s1,
                 s2,
                 sample_rate,
                 window_length,
                 increment,
                 min_freq=0,
                 max_freq=None,
                 return_coherency=False):
    """ Computes the coherence between two signals by averaging across time-frequency representations
        created using a Gaussian-windowed Short-time Fourier Transform. Uses jacknifing to estimate
        the variance of the coherence.

    :param s1: The first signal
    :param s2: The second signal
    :param sample_rate: The sample rates of the signals.
    :param window_length: The length of the window used to compute the STFT (units=seconds)
    :param increment: The spacing between the points of the STFT  (units=seconds)
    :param min_freq: The minimum frequency to analyze (units=Hz, default=0)
    :param max_freq: The maximum frequency to analyze (units=Hz, default=nyquist frequency)
    :param return_coherency: Whether or not to return the time domain coherency (default=False)

    :return: freq,coherence,coherence_var,phase_coherence,phase_coherence_var,[coherency,coherency_t]: freq is an array
             of frequencies that the coherence was computed at. coherence is an array of length len(freq) that contains
             the coherence at each frequency. coherence_var is the variance of the coherence. phase_coherence is the
             average cosine phase difference at each frequency, and phase_coherence_var is the variance of that measure.
             coherency is only returned if return_coherency=True, it is the inverse fourier transform of the complex-
             valued coherency.
    """
    if s1.shape != s2.shape:
        raise AssertionError('s1 and s2 must have the same shape')
    if s1.ndim == 1:
        s1, s2 = [np.array(i, ndmin=2) for i in [s1, s2]]

    tf1, tf2 = list(), list()
    for i, (is1, is2) in enumerate(zip(s1, s2)):
        t1, freq1, itf1, rms1 = gaussian_stft(is1,
                                              sample_rate,
                                              window_length=window_length,
                                              increment=increment,
                                              min_freq=min_freq,
                                              max_freq=max_freq)

        t2, freq2, itf2, rms2 = gaussian_stft(is2,
                                              sample_rate,
                                              window_length=window_length,
                                              increment=increment,
                                              min_freq=min_freq,
                                              max_freq=max_freq)
        tf1.append(itf1)
        tf2.append(itf2)
    tf1, tf2 = [np.hstack(i) for i in [tf1, tf2]]

    cross_spec12 = tf1 * np.conj(tf2)
    ps1 = np.abs(tf1)**2
    ps2 = np.abs(tf2)**2

    # compute the coherence using all the data
    csd = cross_spec12.sum(axis=1)
    denom = ps1.sum(axis=1) * ps2.sum(axis=1)
    c_amp = np.abs(csd) / np.sqrt(denom)
    cohe = c_amp**2

    # compute the phase coherence using all the data
    c_phase = np.cos(np.angle(csd))

    # make leave-one-out estimates of the complex coherence
    jn_estimates_amp = list()
    jn_estimates_phase = list()
    jn_estimates_cohe = list()

    njn = tf1.shape[1]
    for k in range(njn):
        i = np.ones([njn], dtype='bool')
        i[k] = False
        csd = cross_spec12[:, i].sum(axis=1)
        denom = ps1[:, i].sum(axis=1) * ps2[:, i].sum(axis=1)
        c_amp = np.abs(csd) / np.sqrt(denom)
        jn_estimates_amp.append(c_amp)
        jn_estimates_cohe.append(njn * cohe - (njn - 1) * (c_amp**2))

        c_phase = np.cos(np.angle(csd))
        jn_estimates_phase.append(c_phase)

    jn_estimates_amp = np.array(jn_estimates_amp)
    jn_estimates_cohe = np.array(jn_estimates_cohe)
    jn_estimates_phase = np.array(jn_estimates_phase)

    # estimate the variance of the coherence
    jn_mean_amp = jn_estimates_amp.mean(axis=0)
    jn_diff_amp = (jn_estimates_amp - jn_mean_amp)**2
    c_var_amp = ((njn - 1) / float(njn)) * jn_diff_amp.sum(axis=0)
    cohe_unbiased = jn_estimates_cohe.mean(axis=0)
    cohe_se = jn_estimates_cohe.std(axis=0) / np.sqrt(njn)

    # estimate the variance of the phase coherence
    jn_mean_phase = jn_estimates_phase.mean(axis=0)
    jn_diff_phase = (jn_estimates_phase - jn_mean_phase)**2
    c_phase_var = ((njn - 1) / float(njn)) * jn_diff_phase.sum(axis=0)

    assert c_amp.max() <= 1.0, "c_amp.max()=%f" % c_amp.max()
    assert c_amp.min() >= 0.0, "c_amp.min()=%f" % c_amp.min()
    assert np.sum(np.isnan(c_amp)) == 0, "NaNs in c_amp!"

    if return_coherency:
        # compute the complex-valued coherency
        z = csd / denom

        # make the complex-valued coherency symmetric around zero
        sym_z = np.zeros([len(z) * 2 - 1], dtype='complex')
        sym_z[len(z) - 1:] = z
        sym_z[:len(z) - 1] = (z[1:])[::-1]

        # do an fft shift so the inverse fourier transform works
        sym_z = fftshift(sym_z)

        if len(sym_z) % 2 == 1:
            # shift zero from end of shift_lags to beginning
            sym_z = np.roll(sym_z, 1)

        coherency = ifft(sym_z)
        coherency = fftshift(coherency.real)

        dt = 1. / sample_rate
        hc = (len(coherency) - 1) / 2
        coherency_t = np.arange(-hc, hc + 1, 1) * dt
        """
        import matplotlib.pyplot as plt
        plt.figure()
        plt.plot(coherency_t, coherency, 'k-')
        plt.axis('tight')
        plt.show()
        """

        return freq1, c_amp, c_var_amp, c_phase, c_phase_var, coherency, coherency_t, cohe_unbiased, cohe_se
    else:
        return freq1, c_amp, c_var_amp, c_phase, c_phase_var, cohe_unbiased, cohe_se