def launch(self, view_model): # type: (FourierSpectrumModel) -> dict self.log.debug("Plot started...") # these partial loads are dangerous for TS and FS instances, but efficient fs_input_index = self.load_entity_by_gid(view_model.input_data.hex) fourier_spectrum = FourierSpectrum() with h5.h5_file_for_index(fs_input_index) as input_h5: shape = list(input_h5.array_data.shape) fourier_spectrum.segment_length = input_h5.segment_length.load() fourier_spectrum.windowing_function = input_h5.windowing_function.load( ) ts_index = self.load_entity_by_gid(fs_input_index.source_gid) state_list = ts_index.get_labels_for_dimension(1) if len(state_list) == 0: state_list = list(range(shape[1])) fourier_spectrum.source = TimeSeries( sample_period=ts_index.sample_period) mode_list = list(range(shape[3])) available_scales = ["Linear", "Logarithmic"] params = dict(matrix_shape=json.dumps([shape[0], shape[2]]), plotName=ts_index.title, url_base=self.build_h5_url(view_model.input_data.hex, "get_fourier_data", parameter=""), xAxisName="Frequency [kHz]", yAxisName="Power", available_scales=available_scales, state_list=state_list, mode_list=mode_list, normalize_list=["no", "yes"], normalize="no", state_variable=state_list[0], mode=mode_list[0], xscale=available_scales[0], yscale=available_scales[0], x_values=json.dumps(fourier_spectrum.frequency[slice( shape[0])].tolist()), xmin=fourier_spectrum.freq_step, xmax=fourier_spectrum.max_freq) return self.build_display_result("fourier_spectrum/view", params)
def test_fourier_spectrum_model_to_h5(tmph5factory, time_series_index_factory): fs = FourierSpectrum() fsm = FourierSpectrumModel(input_data=fs.gid) path = tmph5factory() h5_file = ViewModelH5(path, fsm) h5_file.store(fsm) h5_file.close() loaded_dt = FourierSpectrumModel() h5_file = ViewModelH5(path, loaded_dt) h5_file.load_into(loaded_dt) assert loaded_dt.input_data == fs.gid assert loaded_dt.gid == fsm.gid
def compute_fast_fourier_transform(time_series, segment_length, window_function, detrend): """ # type: (TimeSeries, float, function, bool) -> FourierSpectrum Calculate the FFT of time_series broken into segments of length segment_length and filtered by window_function. Parameters __________ time_series : TimeSeries The TimeSeries to which the FFT is to be applied. segment_length : float The segment length determines the frequency resolution of the resulting power spectra -- longer windows produce finer frequency resolution window_function : str Windowing functions can be applied before the FFT is performed. Default is None, possibilities are: 'hamming'; 'bartlett';'blackman'; and 'hanning'. See, numpy.<function_name>. detrend : bool Default is True, False means no detrending is performed on the time series. """ tpts = time_series.data.shape[0] time_series_length = tpts * time_series.sample_period # Segment time-series, overlapping if necessary nseg = int(numpy.ceil(time_series_length / segment_length)) if nseg > 1: seg_tpts = numpy.ceil(segment_length / time_series.sample_period) overlap = (seg_tpts * nseg - tpts) / (nseg - 1.0) starts = [max(seg * (seg_tpts - overlap), 0) for seg in range(nseg)] segments = [ time_series.data[int(start):int(start) + int(seg_tpts)] for start in starts ] segments = [segment[:, :, :, :, numpy.newaxis] for segment in segments] ts = numpy.concatenate(segments, axis=4) else: segment_length = time_series_length ts = time_series.data[:, :, :, :, numpy.newaxis] seg_tpts = ts.shape[0] log.debug("Segment length being used is: %s" % segment_length) # Base-line correct the segmented time-series if detrend: ts = scipy.signal.detrend(ts, axis=0) log.debug("time_series " + narray_describe(ts)) # Apply windowing function if window_function is not None: wf = SUPPORTED_WINDOWING_FUNCTIONS[window_function] window_mask = numpy.reshape(wf(int(seg_tpts)), (int(seg_tpts), 1, 1, 1, 1)) ts = ts * window_mask # Calculate the FFT result = numpy.fft.fft(ts, axis=0) nfreq = result.shape[0] // 2 result = result[1:nfreq + 1, :] log.debug("result " + narray_describe(result)) spectra = FourierSpectrum(source=time_series, segment_length=segment_length, array_data=result, windowing_function=window_function) spectra.configure() return spectra
def evaluate(self): """ Calculate the FFT of time_series broken into segments of length segment_length and filtered by window_function. """ tpts = self.time_series.data.shape[0] time_series_length = tpts * self.time_series.sample_period # Segment time-series, overlapping if necessary nseg = int(numpy.ceil(time_series_length / self.segment_length)) if nseg > 1: seg_tpts = numpy.ceil(self.segment_length / self.time_series.sample_period) overlap = (seg_tpts * nseg - tpts) / (nseg - 1.0) starts = [ max(seg * (seg_tpts - overlap), 0) for seg in range(nseg) ] segments = [ self.time_series.data[int(start):int(start) + int(seg_tpts)] for start in starts ] segments = [ segment[:, :, :, :, numpy.newaxis] for segment in segments ] time_series = numpy.concatenate(segments, axis=4) else: self.segment_length = time_series_length time_series = self.time_series.data[:, :, :, :, numpy.newaxis] seg_tpts = time_series.shape[0] self.log.debug("Segment length being used is: %s" % self.segment_length) # Base-line correct the segmented time-series if self.detrend: time_series = scipy.signal.detrend(time_series, axis=0) self.log.debug("time_series " + narray_describe(time_series)) # Apply windowing function if self.window_function is not None: window_function = SUPPORTED_WINDOWING_FUNCTIONS[ self.window_function] window_mask = numpy.reshape(window_function(int(seg_tpts)), (int(seg_tpts), 1, 1, 1, 1)) time_series = time_series * window_mask # Calculate the FFT result = numpy.fft.fft(time_series, axis=0) nfreq = result.shape[0] // 2 result = result[1:nfreq + 1, :] self.log.debug("result " + narray_describe(result)) spectra = FourierSpectrum(source=self.time_series, segment_length=self.segment_length, array_data=result, windowing_function=self.window_function) spectra.configure() return spectra