def launch(self, time_series, segment_length=None, window_function=None): """ Launch algorithm and build results. """ shape = time_series.read_data_shape() block_size = int( math.floor(time_series.read_data_shape()[2] / self.memory_factor)) blocks = int(math.ceil(time_series.read_data_shape()[2] / block_size)) ##----------- Prepare a FourierSpectrum object for result ------------## spectra = spectral.FourierSpectrum( source=time_series, segment_length=self.algorithm.segment_length, window_function=self.algorithm.window_function, storage_path=self.storage_path) ##------------- NOTE: Assumes 4D, Simulator timeSeries. --------------## node_slice = [slice(shape[0]), slice(shape[1]), None, slice(shape[3])] ##---------- Iterate over slices and compose final result ------------## small_ts = datatypes_time_series.TimeSeries(use_storage=False) small_ts.sample_period = time_series.sample_period for block in range(blocks): node_slice[2] = slice(block * block_size, min([(block + 1) * block_size, shape[2]]), 1) small_ts.data = time_series.read_data_slice(tuple(node_slice)) self.algorithm.time_series = small_ts partial_result = self.algorithm.evaluate() spectra.write_data_slice(partial_result) LOG.debug("partial segment_length is %s" % (str(partial_result.segment_length))) spectra.segment_length = partial_result.segment_length spectra.close_file() return spectra
def evaluate(self): """ Calculate the FFT of time_series broken into segments of length segment_length and filtered by window_function. """ cls_attr_name = self.__class__.__name__ + ".time_series" self.time_series.trait["data"].log_debug(owner=cls_attr_name) 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[start:start + 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] LOG.debug("Segment length being used is: %s" % self.segment_length) #Base-line correct the segmented time-series time_series = sp_signal.detrend(time_series, axis=0) util.log_debug_array(LOG, time_series, "time_series") #Apply windowing function if self.window_function is not None and self.window_function != [None]: if self.window_function not in SUPPORTED_WINDOWING_FUNCTIONS: LOG.error("Windowing function is: %s" % self.window_function) LOG.error("Must be in: %s" % str(SUPPORTED_WINDOWING_FUNCTIONS)) else: window_function = eval("".join(("numpy.", self.window_function[0]))) window_mask = numpy.reshape(window_function(seg_tpts), (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, :] util.log_debug_array(LOG, result, "result") spectra = spectral.FourierSpectrum(source=self.time_series, segment_length=self.segment_length, array_data=result, use_storage=False) return spectra
def launch(self, time_series, segment_length=None, window_function=None): """ Launch algorithm and build results. :param time_series: the input time series to which the fft is to be applied :param segment_length: the block size which determines the frequency resolution \ of the resulting power spectra :param window_function: windowing functions can be applied before the FFT is performed :type window_function: None; ‘hamming’; ‘bartlett’; ‘blackman’; ‘hanning’ :returns: the fourier spectrum for the specified time series :rtype: `FourierSpectrum` """ shape = time_series.read_data_shape() block_size = int( math.floor(time_series.read_data_shape()[2] / self.memory_factor)) blocks = int(math.ceil(time_series.read_data_shape()[2] / block_size)) ##----------- Prepare a FourierSpectrum object for result ------------## spectra = spectral.FourierSpectrum( source=time_series, segment_length=self.algorithm.segment_length, windowing_function=str(window_function), storage_path=self.storage_path) ##------------- NOTE: Assumes 4D, Simulator timeSeries. --------------## node_slice = [slice(shape[0]), slice(shape[1]), None, slice(shape[3])] ##---------- Iterate over slices and compose final result ------------## small_ts = datatypes_time_series.TimeSeries(use_storage=False) small_ts.sample_period = time_series.sample_period for block in range(blocks): node_slice[2] = slice(block * block_size, min([(block + 1) * block_size, shape[2]]), 1) small_ts.data = time_series.read_data_slice(tuple(node_slice)) self.algorithm.time_series = small_ts partial_result = self.algorithm.evaluate() if blocks <= 1 and len(partial_result.array_data) == 0: self.add_operation_additional_info( "Fourier produced empty result (most probably due to a very short input TimeSeries)." ) return None spectra.write_data_slice(partial_result) LOG.debug("partial segment_length is %s" % (str(partial_result.segment_length))) spectra.segment_length = partial_result.segment_length spectra.close_file() return spectra
def test_fourierspectrum(self): data = numpy.random.random((10, 10)) ts = time_series.TimeSeries(data=data) dt = spectral.FourierSpectrum(source=ts, segment_length=100) dt.configure() summary_info = dt.summary_info self.assertEqual(summary_info['Frequency step'], 0.01) self.assertEqual(summary_info['Maximum frequency'], 0.5) self.assertEqual(summary_info['Segment length'], 100) self.assertEqual(summary_info['Windowing function'], '') self.assertEqual(summary_info['Source'], '') self.assertEqual(summary_info['Spectral type'], 'FourierSpectrum') self.assertTrue(dt.aggregation_functions is None) self.assertEqual(dt.normalised_average_power.shape, (0, )) self.assertEqual(dt.segment_length, 100.0) self.assertEqual(dt.shape, (0, )) self.assertTrue(dt.source is not None) self.assertEqual(dt.windowing_function, '')
def test_fourierspectrum(self): data = numpy.random.random((10, 10)) ts = time_series.TimeSeries(data=data, title='meh') dt = spectral.FourierSpectrum(source=ts, segment_length=100, array_data=numpy.array([]), windowing_function = str('')) summary_info = dt.summary_info() assert summary_info['Frequency step'] == 0.01 assert summary_info['Maximum frequency'] == 0.5 assert summary_info['Segment length'] == 100 assert summary_info['Windowing function'] is not None assert summary_info['Source'] == 'meh' assert summary_info['Spectral type'] == 'FourierSpectrum' assert dt.normalised_average_power is None assert dt.segment_length == 100.0 assert dt.array_data is not None assert dt.source is not None assert dt.windowing_function is not None
def test_fourierspectrum(self): data = numpy.random.random((10, 10)) ts = time_series.TimeSeries(data=data) dt = spectral.FourierSpectrum(source=ts, segment_length=100) dt.configure() summary_info = dt.summary_info assert summary_info['Frequency step'] == 0.01 assert summary_info['Maximum frequency'] == 0.5 assert summary_info['Segment length'] == 100 assert summary_info['Windowing function'] == '' assert summary_info['Source'] == '' assert summary_info['Spectral type'] == 'FourierSpectrum' assert dt.aggregation_functions is None assert dt.normalised_average_power.shape == (0, ) assert dt.segment_length == 100.0 assert dt.shape == (0, ) assert dt.source is not None assert dt.windowing_function == ''