def test_fft_spectrum_04():
    f, t, Sxx = _spectral_helper(x,
                                 x,
                                 fs=s_freq,
                                 window='hann',
                                 nperseg=x.shape[0],
                                 noverlap=0,
                                 nfft=None,
                                 return_onesided=False,
                                 mode='psd',
                                 scaling='spectrum')

    f0, Sxx0 = _fft(x,
                    s_freq,
                    detrend=None,
                    taper='hann',
                    scaling='energy',
                    sides='two')

    assert_array_equal(f0, f)
    assert_array_almost_equal(Sxx0, Sxx[:, 0] * CORRECTION_FACTOR)
def test_fft_spectrum_01():
    f, t, Sxx = _spectral_helper(x,
                                 x,
                                 fs=s_freq,
                                 window='hann',
                                 nperseg=x.shape[0],
                                 noverlap=0,
                                 nfft=None,
                                 return_onesided=True,
                                 mode='psd',
                                 scaling='density')

    f0, Sxx0 = _fft(x,
                    s_freq,
                    detrend=None,
                    taper='hann',
                    scaling='power',
                    sides='one')

    assert_array_equal(f0, f)
    assert_array_almost_equal(Sxx0, Sxx[:, 0])
def test_fft_spectrum_06():
    f, t, Sxx = _spectral_helper(x,
                                 x,
                                 fs=s_freq,
                                 window='hann',
                                 nperseg=x.shape[0],
                                 noverlap=0,
                                 nfft=None,
                                 return_onesided=False,
                                 mode='stft',
                                 scaling='spectrum')

    f0, Sxx0 = _fft(x,
                    s_freq,
                    detrend=None,
                    taper='hann',
                    scaling='energy',
                    output='complex',
                    sides='two')

    assert_array_equal(f0, f)
    # in scipy, the extra dim is time, in wonambi it's the taper
    assert_array_almost_equal(Sxx0[:, 0], Sxx[:, 0] * sqrt(CORRECTION_FACTOR))
def test_fft_spectrum_02():
    """Scipy does not correct the energy with the spectrum scaling
    when windowing."""
    f, t, Sxx = _spectral_helper(x,
                                 x,
                                 fs=s_freq,
                                 window='hann',
                                 nperseg=x.shape[0],
                                 noverlap=0,
                                 nfft=None,
                                 return_onesided=True,
                                 mode='psd',
                                 scaling='spectrum')

    f0, Sxx0 = _fft(x,
                    s_freq,
                    detrend=None,
                    taper='hann',
                    scaling='energy',
                    sides='one')

    assert_array_equal(f0, f)
    assert_array_almost_equal(Sxx0, Sxx[:, 0] * CORRECTION_FACTOR)
Beispiel #5
0
def bandpower(data, bands, epoch_size, epoch_overlap, fs=None, scaling='density', relative=False):
    # Note: add to doc that epoch_size and epoch_overlap is in seconds
    # also,
    # TODO: add on documentation of estimate_rate that the output is in Hz

    if isinstance(data, (pd.DataFrame, pd.Series)) and isinstance(data.index, (pd.TimedeltaIndex, pd.DatetimeIndex)):
        datetime_index = True
        fs = fs or int(estimate_rate(data))
        if isinstance(data, pd.DataFrame):
            columns = data.columns
            x = np.asarray(data.values)
        else:
            columns = [data.name]
            x = np.asarray(data.values)[:, np.newaxis]
    else:
        datetime_index = False
        x = np.asarray(data)
        if x.ndim not in (1, 2):
            raise ValueError('bandpower only supports 1- or 2-dimensional data')
        elif x.ndim == 1:
            x = x[:, np.newaxis]
        columns = [f'x{i+1}' for i in range(x.shape[1])]
        fs = fs or 1

    logger.debug('Calculating %s spectra with fs=%dHz on data shaped as %s',
                 'relative' if relative else 'absolute', fs, data.shape)

    x = x.T
    nsamples = x.shape[1]
    nperseg = int(epoch_size * fs)
    noverlap = int(epoch_overlap * fs)
    if nperseg > nsamples:
        raise ValueError('Epoch size is larger than data')

    # To whom it may concern: according to the _spectral_helper code, the
    # difference between scaling='density' and 'spectrum' is just how the
    # window adjusts the final value. One uses the sum of squared values, the
    # other the square of the sum. The 'density' also divides by the fs (which
    # is why the units change to V^2 / Hz).
    # In my opinion, this is not very important as long as we are consistent
    freqs, t, psd = _spectral_helper(x, x, fs=fs, window='hann',
                                     nperseg=nperseg, noverlap=noverlap,
                                     detrend='constant', return_onesided=True,
                                     scaling=scaling, mode='psd')  # TODO: psd or stft ???

    # Manage index
    if datetime_index:
        index = data.index[0] + pd.to_timedelta(t, unit='s')
    else:
        #
        index = pd.Index((t * (nperseg - noverlap)).astype(int),
                         name='sample')
    n = index.shape[0]

    powers = []
    rel_suffix = '_rel' if relative else '_abs'
    for name, (f_start, f_stop) in bands.items():
        f_start = f_start or 0
        f_stop = f_stop or fs / 2
        idx = (freqs >= f_start) & (freqs < f_stop)
        if idx.sum() == 0:
            logger.warning('Band %s is empty for fs=%d and nperseg=%d',
                           name, fs, nperseg)
            result = pd.DataFrame(data=[[np.nan] * len(columns)] * n,
                                  columns=columns,
                                  index=index)
        else:
            logger.debug('Calculating band power for %s with %d bins',
                         name, idx.sum())
            if idx.sum() <= 1:
                logger.warning('Band power for %s will be zero because there '
                               'are not enough frequency points to calculate an '
                               'integral', name)
            # TODO: we should manage the 1-bin case, but how ?
            # pxx axes: (column, freq, time)
            # bp = psd[:, idx, :].sum(axis=1)
            bp = simps(psd[:, idx, :], freqs[idx], axis=1)

            if relative:
                bp /= simps(psd, freqs, axis=1)

            # power_sum axes: (column, time)
            result = pd.DataFrame(data=bp.T,  # (time, column)
                                  columns=columns,
                                  index=index)

        powers.append(result.add_suffix(f'_{name}{rel_suffix}'))

    return pd.concat(powers, axis='columns')
Beispiel #6
0
    def calc_csd(self):
        """
        Calculate the cross spectral density using Scipy csd function.

        csd utilizes Welch's method to estimate spectral density. Data is
        split into overlapping segments. Each segment is windowed, then the
        cross spectral density is calculated using Fourier transforms. The
        results from all windows are averaged together to produce a lower
        variance estimate of the spectral density.

        A segment overlap factor of 2 is used (50% overlap).
        A one-sided spectrum is returned for real inputs
        The cross spectral density (units V**2/Hz) is calculated, as
        opposed to the cross spectrum (units V**2).

        csd is a 2D array containing the cross spectral density. Axis 0 is the
        frequency axis and axis 1 is the time axis. Entries in the times array
        are the center values for each time bin.
        """

        # If the number of points per segement is not specified, calculate the
        # number that gives approximately equal time and frequency resolution.
        if self.nperseg is None:
            self.nperseg = int(np.sqrt(2 * self.numpnts))

        # Use next power of 2 for nperseg if specified. FFT algorithm is most
        # efficient when nperseg is a power of 2.
        if self.forcepower2 is True:
            self.nperseg = np.power(2, int(np.log2(self.nperseg - 1)) + 1)

        # Calculate cross spectral density
        self.freqs, self.times, self.csd = _spectral_helper(
            self.signal1,
            self.signal2,
            fs=self.fSample,
            window=self.window,
            nperseg=self.nperseg,
            detrend=self.detrend,
            scaling='density',
            mode='psd')

        # Calculate auto spectral density of signal 1
        _, _, self.asd1 = _spectral_helper(self.signal1,
                                           self.signal1,
                                           fs=self.fSample,
                                           window=self.window,
                                           nperseg=self.nperseg,
                                           detrend=self.detrend,
                                           scaling='density',
                                           mode='psd')

        # Calculate auto spectral density of signal 2
        _, _, self.asd2 = _spectral_helper(self.signal2,
                                           self.signal2,
                                           fs=self.fSample,
                                           window=self.window,
                                           nperseg=self.nperseg,
                                           detrend=self.detrend,
                                           scaling='density',
                                           mode='psd')

        # Shift time bins to correspond to original data window
        self.times += (self.signal1time[0] + self.signal2time[0]) / 2

        # Remove bins with sawtooth crashes
        if self.sawteethtimes is not None:
            self.remove_sawteeth()

        # Record number of bins (aka # segments or # realizations) in the ffts
        self.numbins = np.shape(self.csd)[-1]

        # Calculate time bin averaged spectral densities
        self.csd_binavg = np.mean(self.csd, axis=-1)
        self.asd1_binavg = np.mean(self.asd1, axis=-1)
        self.asd2_binavg = np.mean(self.asd2, axis=-1)

        # Convert frequency units from Hz to kHz
        self.freqs /= 1000
Beispiel #7
0
    def calc_csd(self):
        """
        Calculate the cross spectral density using Scipy csd function.

        csd utilizes Welch's method to estimate spectral density. Data is
        split into overlapping segments. Each segment is windowed, then the
        cross spectral density is calculated using Fourier transforms. The
        results from all windows are averaged together to produce a lower
        variance estimate of the spectral density.

        A segment overlap factor of 2 is used (50% overlap).
        A one-sided spectrum is returned for real inputs
        The cross spectral density (units V**2/Hz) is calculated, as
        opposed to the cross spectrum (units V**2).

        csd is a 2D array containing the cross spectral density. Axis 0 is the
        frequency axis and axis 1 is the time axis. Entries in the times array
        are the center values for each time bin.
        """

        # If the number of points per segement is not specified, calculate the
        # number that gives approximately equal time and frequency resolution.
        if self.nperseg is None:
            self.nperseg = int(np.sqrt(2 * self.numpnts))

        # Use next power of 2 for nperseg if specified. FFT algorithm is most
        # efficient when nperseg is a power of 2.
        if self.forcepower2 is True:
            self.nperseg = np.power(2, int(np.log2(self.nperseg - 1)) + 1)

        # Calculate cross spectral density
        self.freqs, self.times, self.csd = _spectral_helper(
            self.signal1,
            self.signal2,
            fs=self.fSample,
            window=self.window,
            nperseg=self.nperseg,
            detrend=self.detrend,
            scaling='density',
            mode='psd'
        )

        # Calculate auto spectral density of signal 1
        _, _, self.asd1 = _spectral_helper(
            self.signal1,
            self.signal1,
            fs=self.fSample,
            window=self.window,
            nperseg=self.nperseg,
            detrend=self.detrend,
            scaling='density',
            mode='psd'
        )

        # Calculate auto spectral density of signal 2
        _, _, self.asd2 = _spectral_helper(
            self.signal2,
            self.signal2,
            fs=self.fSample,
            window=self.window,
            nperseg=self.nperseg,
            detrend=self.detrend,
            scaling='density',
            mode='psd'
        )

        # Shift time bins to correspond to original data window
        self.times += (self.signal1time[0] + self.signal2time[0]) / 2

        # Remove bins with sawtooth crashes
        if self.sawteethtimes is not None:
            self.remove_sawteeth()

        # Record number of bins (aka # segments or # realizations) in the ffts
        self.numbins = np.shape(self.csd)[-1]

        # Calculate time bin averaged spectral densities
        self.csd_binavg = np.mean(self.csd, axis=-1)
        self.asd1_binavg = np.mean(self.asd1, axis=-1)
        self.asd2_binavg = np.mean(self.asd2, axis=-1)

        # Convert frequency units from Hz to kHz
        self.freqs /= 1000
        #     plt.colorbar()
    # plt.get_current_fig_manager().window.raise_()
    # plt.show()
    plt.savefig('{}/{} spectragram {}.png'.format(dir_temp_fig, filename_common, data_neuro['signal_info'][j]['name']))
    plt.close()
plt.ion()


# ==========
# coherence


from scipy.signal import spectral
ch_x=05-1
ch_y=38-1
[spcg_f,spcg_t,spcg_xy] = spectral._spectral_helper(data_neuro['data'][:,:,ch_x], data_neuro['data'][:,:,ch_y], window=signal.hann(128), nperseg=128, nfft=256,fs=data_neuro['signal_info'][0][2], axis=1, noverlap=96)
[_,_,spcg_xx] = spectral._spectral_helper(data_neuro['data'][:,:,ch_x], data_neuro['data'][:,:,ch_x], window=signal.hann(128), nperseg=128, nfft=256,fs=data_neuro['signal_info'][0][2], axis=1, noverlap=96)
[_,_,spcg_yy] = spectral._spectral_helper(data_neuro['data'][:,:,ch_y], data_neuro['data'][:,:,ch_y], window=signal.hann(128), nperseg=128, nfft=256,fs=data_neuro['signal_info'][0][2], axis=1, noverlap=96)

spcg_t = np.array(spcg_t) + np.array( data_neuro['ts'][0] )
data_neuro = signal_align.neuro_sort(data_df, ['stim_familiarized', 'mask_opacity_int'], [], data_neuro )
data_neuro_full = data_neuro

if False:
    data_neuro = signal_align.neuro_sort(data_df, ['stim_names'], np.logical_and(data_df['mask_opacity_int']==0, data_df['stim_familiarized']==0), data_neuro )
    indx_used = data_neuro['cdtn_indx'][temp['cdtn'][0]]
    [spcg_f,spcg_t,spcg_xy] = spectral._spectral_helper(data_neuro['data'][indx_used,:,ch_x], data_neuro['data'][indx_used,:,ch_y], window=signal.hann(128), nperseg=128, nfft=256,fs=data_neuro['signal_info'][0][2], axis=1, noverlap=96)

# by condition
plt.figure(figsize=(16,9))
spcg_cdtn = []