This is an automated email from the git hooks/post-receive script. yoh pushed a commit to tag 0.4 in repository python-mne.
commit 08fbe22078d52227b0b306b9058c26de6ce2348a Author: Martin Luessi <[email protected]> Date: Mon Mar 5 11:10:39 2012 -0500 Save memory if n_jobs=1 and dtype stays the same --- mne/fiff/raw.py | 122 ++++++++++++++++++++++++--------------------- mne/fiff/tests/test_raw.py | 9 ++-- 2 files changed, 69 insertions(+), 62 deletions(-) diff --git a/mne/fiff/raw.py b/mne/fiff/raw.py index 20ff73b..4fb12b0 100644 --- a/mne/fiff/raw.py +++ b/mne/fiff/raw.py @@ -232,48 +232,15 @@ class Raw(object): # set the data self._data[sel, start:stop] = value - def analytic_signal(self, picks, n_jobs=1, verbose=5): - """ Compute analytic signal for a subset of channels. - - Compute analytic signal for the channels defined in "picks". The - data of the Raw object is modified inplace and converted to a - complex representation (the analytic signal is complex valued). - - The Raw object has to be constructed using preload=True (or string). - - Parameters - ---------- - picks : list of int - Indices of channels to apply the function to. - - n_jobs: int - Number of jobs to run in parallel. - - verbose: int - Verbosity level. - - Notes - ----- - The analytic signal "x_a(t)" of "x(t)" is:: - - x_a = F^{-1}(F(x) 2U) = x + i y - - where "F" is the Fourier transform, "U" the unit step function, - and "y" the Hilbert transform of "x". One usage of the analytic - signal is the computation of the enevelope signal, which is given by - "e(t) = abs(x_a(t))". Due to the linearity of Hilbert transform and the - MNE inverse solution, the enevlope in source space can be obtained - by computing the analytic signal in sensor space, applying the MNE - inverse, and computing the envelope in source space. - """ - self.apply_function(hilbert, picks, n_jobs, verbose) - - - def apply_function(self, fun, picks, n_jobs, verbose, *args, **kwargs): + def apply_function(self, fun, picks, dtype, n_jobs, verbose, *args, + **kwargs): """ Apply a function to a subset of channels. The function "fun" is applied to the channels defined in "picks". The - data of the Raw object is modified inplace. + data of the Raw object is modified inplace. If the function returns + a different data type (e.g. numpy.complex) it must be specified using + the dtype parameter, which causes the data type used for representing + the raw data to change. The Raw object has to be constructed using preload=True (or string). @@ -287,6 +254,10 @@ class Raw(object): picks : list of int Indices of channels to apply the function to. + dtype : numpy.dtype + Data type to use for raw data after applying the function. If None + the data type is not modified. + n_jobs: int Number of jobs to run in parallel. @@ -307,24 +278,59 @@ class Raw(object): if not callable(fun): raise ValueError('fun needs to be a function') - # create parallel function - parallel, p_fun, _ = parallel_func(fun, n_jobs, verbose) + data_in = self._data + if dtype is not None and dtype != self._data.dtype: + self._data = self._data.astype(dtype) + + if n_jobs == 1: + # modify data inplace to save memory + for idx in picks: + self._data[idx, :] = fun(data_in[idx, :], *args, **kwargs) + else: + # use parallel function + parallel, p_fun, _ = parallel_func(fun, n_jobs, verbose) + + data_picks = data_in[picks, :] + data_picks_new = np.array(parallel(p_fun(x, *args, **kwargs) + for x in data_picks)) + + self._data[picks, :] = data_picks_new + + def apply_hilbert(self, picks, n_jobs=1, verbose=5): + """ Compute analytic signal for a subset of channels. + + Compute analytic signal for the channels defined in "picks". The + data of the Raw object is modified inplace and converted to a + complex representation (the analytic signal is complex valued). - # apply function to channels - data_picks = self._data[picks, :] - data_picks_new = np.array(parallel(p_fun(x, *args, **kwargs) - for x in data_picks)) + The Raw object has to be constructed using preload=True (or string). - if np.any(data_picks_new.shape != data_picks.shape): - raise ValueError('fun must return array with the same size as ' - 'input') + Parameters + ---------- + picks : list of int + Indices of channels to apply the function to. - # convert the type of _data if necessary - if data_picks_new.dtype != self._data.dtype: - print 'Converting raw data to %s' % data_picks_new.dtype - self._data = np.array(self._data, dtype=data_picks_new.dtype) + n_jobs: int + Number of jobs to run in parallel. - self._data[picks, :] = data_picks_new + verbose: int + Verbosity level. + + Notes + ----- + The analytic signal "x_a(t)" of "x(t)" is:: + + x_a = F^{-1}(F(x) 2U) = x + i y + + where "F" is the Fourier transform, "U" the unit step function, + and "y" the Hilbert transform of "x". One usage of the analytic + signal is the computation of the enevelope signal, which is given by + "e(t) = abs(x_a(t))". Due to the linearity of Hilbert transform and the + MNE inverse solution, the enevlope in source space can be obtained + by computing the analytic signal in sensor space, applying the MNE + inverse, and computing the envelope in source space. + """ + self.apply_function(hilbert, picks, np.complex64, n_jobs, verbose) def band_pass_filter(self, picks, f_low, f_high, filter_length=None, n_jobs=1, verbose=5): @@ -359,7 +365,7 @@ class Raw(object): Verbosity level. """ fs = float(self.info['sfreq']) - self.apply_function(band_pass_filter, picks, n_jobs, verbose, fs, + self.apply_function(band_pass_filter, picks, None, n_jobs, verbose, fs, f_low, f_high, filter_length=filter_length) def high_pass_filter(self, picks, fp, filter_length=None, n_jobs=1, @@ -393,8 +399,8 @@ class Raw(object): """ fs = float(self.info['sfreq']) - self.apply_function(high_pass_filter, picks, n_jobs, verbose, fs, fp, - filter_length=filter_length) + self.apply_function(high_pass_filter, picks, None, n_jobs, verbose, + fs, fp, filter_length=filter_length) def low_pass_filter(self, picks, fp, filter_length=None, n_jobs=1, verbose=5): @@ -426,8 +432,8 @@ class Raw(object): Verbosity level. """ fs = float(self.info['sfreq']) - self.apply_function(low_pass_filter, picks, n_jobs, verbose, fs, fp, - filter_length=filter_length) + self.apply_function(low_pass_filter, picks, None, n_jobs, verbose, + fs, fp, filter_length=filter_length) def save(self, fname, picks=None, tmin=0, tmax=None, buffer_size_sec=10, drop_small_buffer=False): diff --git a/mne/fiff/tests/test_raw.py b/mne/fiff/tests/test_raw.py index 2ceb6a2..744a36b 100644 --- a/mne/fiff/tests/test_raw.py +++ b/mne/fiff/tests/test_raw.py @@ -148,7 +148,7 @@ def test_filter(): picks = picks_meg[:4] raw_lp = deepcopy(raw) - raw_lp.low_pass_filter(picks, 4.0, verbose=0) + raw_lp.low_pass_filter(picks, 4.0, verbose=0, n_jobs=2) raw_hp = deepcopy(raw) raw_hp.high_pass_filter(picks, 8.0, verbose=0) @@ -170,12 +170,13 @@ def test_filter(): assert_array_equal(data, bp_data) -def test_analytic(): - """ Test computation of analytic signal """ + +def test_hilbert(): + """ Test computation of analytic signal using hilbert """ raw = Raw(fif_fname, preload=True) picks_meg = pick_types(raw.info, meg=True) picks = picks_meg[:4] - raw.analytic_signal(picks, verbose=0) + raw.apply_hilbert(picks, verbose=0) #XXX what to test? -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/python-mne.git _______________________________________________ debian-med-commit mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit
