コード例 #1
0
	def calculate_cwt(self, f_center=None, verbose=False, optimize=False, fit=False):
		'''
		Calculate instantaneous frequency using continuous wavelet transfer
		
		wavelet specified in self.wavelet. See PyWavelets CWT documentation
		
		Parameters
		----------
		Optimize : bool, optionals
			Currently placeholder for iteratively determining wavelet scales
		'''

		# wavlist = pywt.wavelist(kind='continuous')
		# w0, wavelet_increment, cwt_scale = self.__get_cwt__()

		# determine if scales will capture the relevant frequency
		if not f_center:
			f_center = self.drive_freq

		dt = 1 / self.sampling_rate
		sc = pywt.scale2frequency(self.wavelet, self.scales) / dt
		if self.verbose:
			print('Wavelet scale from', np.min(sc), 'to', np.max(sc))

		if f_center < np.min(sc) or f_center > np.max(sc):
			raise ValueError('Choose a scale that captures frequency of interest')

		if optimize:
			print('!')
			drive_bin = self.scales[np.searchsorted(sc, f_center)]
			hi = int(1.2 * drive_bin)
			lo = int(0.8 * drive_bin)
			self.scales = np.arange(hi, lo, -0.1)

		spectrogram, freq = pywt.cwt(self.signal, self.scales, self.wavelet, sampling_period=dt)

		if not fit:

			inst_freq, amplitude, _ = parab.ridge_finder(np.abs(spectrogram), np.arange(len(freq)))

		# slow serial curve fitting
		else:

			inst_freq = np.zeros(self.n_points)
			amplitude = np.zeros(self.n_points)

			for c in range(spectrogram.shape[1]):

				SIG = spectrogram[:, c]
				if fit:
					pk = np.argmax(np.abs(SIG))
					popt = np.polyfit(np.arange(20),
									  np.abs(SIG[pk - 10:pk + 10]), 2)
					inst_freq[c] = -0.5 * popt[1] / popt[0]
					amplitude[c] = np.abs(SIG)[pk]

		# rescale to correct frequency 
		inst_freq = pywt.scale2frequency(self.wavelet, inst_freq + self.scales[0]) / dt

		phase = spg.cumtrapz(inst_freq)
		phase = np.append(phase, phase[-1])
		tidx = int(self.tidx * len(inst_freq) / self.n_points)

		self.amplitude = amplitude
		self.inst_freq_raw = inst_freq
		self.inst_freq = -1 * (inst_freq - inst_freq[tidx])  # -1 due to way scales are ordered
		self.spectrogram = np.abs(spectrogram)
		self.wavelet_freq = freq  # the wavelet frequencies

		# subtract the w*t line (drive frequency line) from phase
		start = int(0.3 * tidx)
		end = int(0.7 * tidx)
		xfit = np.polyfit(np.arange(start, end), phase[start:end], 1)
		phase -= (xfit[0] * np.arange(len(inst_freq))) + xfit[1]

		self.phase = phase

		return
コード例 #2
0
	def calculate_stft(self, time_res=20e-6, nfft=200):
		'''
		Sliding FFT approach
		
		Parameters
		----------
		time_res : float, optional
			What timescale to evaluate each FFT over
				  
		fit : bool, optional
			Fits a parabola to the frequency peak to get the actual frequency
			Otherwise defaults to parabolic interpolation (see parab.fit)
		
		nfft : int
			Length of FFT calculated in the spectrogram. More points gets much slower
			but the longer the FFT the finer the frequency bin spacing            
		'''

		pts_per_ncycle = int(time_res * self.sampling_rate)

		if nfft < pts_per_ncycle:
			print('Error with nfft setting')
			nfft = pts_per_ncycle

		# drivebin = int(self.drive_freq / (self.sampling_rate / nfft ))
		freq, times, spectrogram = sps.spectrogram(self.signal,
												   self.sampling_rate,
												   nperseg=pts_per_ncycle,
												   noverlap=pts_per_ncycle - 1,
												   nfft=nfft,
												   window=self.window,
												   mode='magnitude')

		# Parabolic ridge finder
		inst_freq, amplitude, _ = parab.ridge_finder(spectrogram, freq)

		# Correctly pad the signals
		_pts = self.n_points - len(inst_freq)
		_pre = int(np.floor(_pts / 2))
		_post = int(np.ceil(_pts / 2))

		inst_freq = np.pad(inst_freq, (_pre, _post))
		amplitude = np.pad(amplitude, (_pre, _post))

		phase = spg.cumtrapz(inst_freq)
		phase = np.append(phase, phase[-1])
		tidx = int(self.tidx * len(inst_freq) / self.n_points)

		self.amplitude = amplitude
		self.inst_freq_raw = inst_freq
		self.inst_freq = inst_freq - inst_freq[tidx]
		self.spectrogram = spectrogram
		self.stft_freq = freq
		self.stft_times = times

		# subtract the w*t line (drive frequency line) from phase
		start = int(0.3 * tidx)
		end = int(0.7 * tidx)
		xfit = np.polyfit(np.arange(start, end), phase[start:end], 1)
		phase -= (xfit[0] * np.arange(len(inst_freq))) + xfit[1]

		self.phase = phase

		return
コード例 #3
0
ファイル: pixel.py プロジェクト: rajgiriUW/ffta
    def calculate_stft(self, nfft=200, calc_phase=False):
        '''
        Sliding FFT approach
        
        :param nfft: Length of FFT calculated in the spectrogram. More points gets much slower
            but the longer the FFT the finer the frequency bin spacing
        :type nfft: int
               
        :param calc_phase: Calculates teh Phase (not usually needed)
        :type calc_phase: bool, optional
            
        '''

        pts_per_ncycle = int(self.fft_time_res * self.sampling_rate)

        if nfft < pts_per_ncycle:
            print('Error with nfft setting')
            nfft = pts_per_ncycle

        if pts_per_ncycle > len(self.signal):
            pts_per_ncycle = len(self.signal)

        # drivebin = int(self.drive_freq / (self.sampling_rate / nfft ))
        freq, times, spectrogram = sps.spectrogram(self.signal,
                                                   self.sampling_rate,
                                                   nperseg=pts_per_ncycle,
                                                   noverlap=pts_per_ncycle - 1,
                                                   nfft=nfft,
                                                   window=self.window,
                                                   mode='magnitude')

        # Parabolic ridge finder
        inst_freq, amplitude, _ = parab.ridge_finder(spectrogram, freq)

        # Correctly pad the signals
        _pts = self.n_points - len(inst_freq)
        _pre = int(np.floor(_pts / 2))
        _post = int(np.ceil(_pts / 2))

        inst_freq = np.pad(inst_freq, (_pre, _post))
        amplitude = np.pad(amplitude, (_pre, _post))

        if calc_phase:
            phase = spg.cumtrapz(inst_freq)
            phase = np.append(phase, phase[-1])
        else:
            phase = np.zeros(len(inst_freq))
        tidx = int(self.tidx * len(inst_freq) / self.n_points)

        self.amplitude = amplitude
        self.inst_freq_raw = inst_freq
        self.inst_freq = inst_freq - inst_freq[tidx]
        self.spectrogram = spectrogram
        self.stft_freq = freq
        self.stft_times = times

        # subtract the w*t line (drive frequency line) from phase
        if calc_phase:
            start = int(0.3 * tidx)
            end = int(0.7 * tidx)
            xfit = np.polyfit(np.arange(start, end), phase[start:end], 1)
            phase -= (xfit[0] * np.arange(len(inst_freq))) + xfit[1]

        self.phase = phase

        return