[med-svn] [python-mne] 88/353: ENH : support algebra of covariance matrices + fix writing when cov is computed in python

Yaroslav Halchenko debian at onerussian.com
Fri Nov 27 17:24:35 UTC 2015


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 0c22e6093c8ba04d800ec856e3363b3d13c257a0
Author: Alexandre Gramfort <alexandre.gramfort at inria.fr>
Date:   Tue Feb 28 10:52:47 2012 +0100

    ENH : support algebra of covariance matrices + fix writing when cov is computed in python
---
 mne/cov.py            | 79 +++++++++++++++++++++++++++++++++++++++++++++++++--
 mne/tests/test_cov.py | 38 +++++++++++++++++++++----
 2 files changed, 109 insertions(+), 8 deletions(-)

diff --git a/mne/cov.py b/mne/cov.py
index 091829b..086f50e 100644
--- a/mne/cov.py
+++ b/mne/cov.py
@@ -23,8 +23,40 @@ from .fiff.pick import pick_types, channel_indices_by_type
 from .epochs import _is_good
 
 
+def _check_covs_algebra(cov1, cov2):
+    if cov1.ch_names != cov2.ch_names:
+        raise ValueError('Both Covariance do not have the same list of '
+                         'channels.')
+    if map(str, cov1._cov['projs']) != map(str, cov2._cov['projs']):
+        raise ValueError('Both Covariance do not have the same list of '
+                         'SSP projections.')
+    if cov1._cov['bads'] != cov2._cov['bads']:
+        raise ValueError('Both Covariance do not have the same list of '
+                         'bad channels.')
+
+
 class Covariance(object):
-    """Noise covariance matrix"""
+    """Noise covariance matrix
+
+    Parameters
+    ----------
+    fname: string
+        The name of the raw file
+
+    kind: 'full' | 'diagonal'
+        The type of covariance.
+
+    Attributes
+    ----------
+    data : 2D array of shape [n_channels x n_channels]
+        The covariance
+
+    ch_names: list of string
+        List of channels' names
+
+    nfree : int
+        Number of degrees of freedom i.e. number of time points used
+    """
 
     _kind_to_id = dict(full=1, sparse=2, diagonal=3)  # XXX : check
     _id_to_kind = {1: 'full', 2: 'sparse', 3: 'diagonal'}  # XXX : check
@@ -49,6 +81,7 @@ class Covariance(object):
         self._cov = cov
         self.data = cov['data']
         self.ch_names = cov['names']
+        self.nfree = cov['nfree']
 
     def save(self, fname):
         """save covariance matrix in a FIF file"""
@@ -60,6 +93,23 @@ class Covariance(object):
         s += ", data : %s" % self.data
         return "Covariance (%s)" % s
 
+    def __add__(self, cov):
+        """Add Covariance taking into account number of degrees of freedom"""
+        _check_covs_algebra(self, cov)
+        this_cov = copy.deepcopy(cov)
+        this_cov.data[:] += self.data
+        this_cov._cov['nfree'] += self._cov['nfree']
+        this_cov.nfree = this_cov._cov['nfree']
+        return this_cov
+
+    def __iadd__(self, cov):
+        """Add Covariance taking into account number of degrees of freedom"""
+        _check_covs_algebra(self, cov)
+        self.data[:] += cov.data
+        self._cov['nfree'] += cov._cov['nfree']
+        self.nfree = cov._cov['nfree']
+        return self
+
 
 ###############################################################################
 # IO
@@ -125,8 +175,8 @@ def read_cov(fid, node, cov_kind):
                     #   Diagonal is stored
                     data = tag.data
                     diagmat = True
-                    print '    %d x %d diagonal covariance (kind = %d) found.' \
-                                                        % (dim, dim, cov_kind)
+                    print ('    %d x %d diagonal covariance (kind = %d) found.'
+                                                        % (dim, dim, cov_kind))
 
             else:
                 from scipy import sparse
@@ -263,6 +313,18 @@ def compute_raw_data_covariance(raw, tmin=None, tmax=None, tstep=0.2,
     cov = Covariance(None)
     cov.data = data
     cov.ch_names = [raw.info['ch_names'][k] for k in picks_data]
+    cov.nfree = n_samples
+
+    # XXX : do not compute eig and eigvec now (think it's better...)
+    eig = None
+    eigvec = None
+
+    #   Store structure for fif
+    cov._cov = dict(kind=1, diag=False, dim=len(data), names=cov.ch_names,
+                    data=data, projs=copy.deepcopy(raw.info['projs']),
+                    bads=raw.info['bads'], nfree=n_samples, eig=eig,
+                    eigvec=eigvec)
+
     return cov
 
 
@@ -310,6 +372,17 @@ def compute_covariance(epochs, keep_sample_mean=True):
     cov = Covariance(None)
     cov.data = data
     cov.ch_names = ch_names
+    cov.nfree = n_samples
+
+    # XXX : do not compute eig and eigvec now (think it's better...)
+    eig = None
+    eigvec = None
+
+    #   Store structure for fif
+    cov._cov = dict(kind=1, diag=False, dim=len(data), names=ch_names,
+                    data=data, projs=copy.deepcopy(epochs.info['projs']),
+                    bads=epochs.info['bads'], nfree=n_samples, eig=eig,
+                    eigvec=eigvec)
 
     print "Number of samples used : %d" % n_samples
     print '[done]'
diff --git a/mne/tests/test_cov.py b/mne/tests/test_cov.py
index 2124f02..ab28ab1 100644
--- a/mne/tests/test_cov.py
+++ b/mne/tests/test_cov.py
@@ -29,11 +29,8 @@ def test_io_cov():
 
     write_cov_file('cov.fif', cov)
 
-    fid, tree, _ = fiff_open('cov.fif')
-    cov2 = read_cov(fid, tree, cov_type)
-    fid.close()
-
-    assert_array_almost_equal(cov['data'], cov2['data'])
+    cov2 = Covariance('cov.fif')
+    assert_array_almost_equal(cov['data'], cov2.data)
 
 
 def test_cov_estimation_on_raw_segment():
@@ -48,6 +45,14 @@ def test_cov_estimation_on_raw_segment():
     assert_true(linalg.norm(cov.data - cov_mne.data, ord='fro')
             / linalg.norm(cov.data, ord='fro')) < 1e-6
 
+    # test IO when computation done in Python
+    cov.save('test-cov.fif')  # test saving
+    cov_read = Covariance('test-cov.fif')
+    assert_true(cov_read.ch_names == cov.ch_names)
+    assert_true(cov_read.nfree == cov.nfree)
+    assert_true((linalg.norm(cov.data - cov_read.data, ord='fro')
+            / linalg.norm(cov.data, ord='fro')) < 1e-5)
+
 
 def test_cov_estimation_with_triggers():
     """Estimate raw with triggers
@@ -73,3 +78,26 @@ def test_cov_estimation_with_triggers():
     assert_true(cov_mne.ch_names == cov.ch_names)
     assert_true((linalg.norm(cov.data - cov_mne.data, ord='fro')
             / linalg.norm(cov.data, ord='fro')) < 0.06)
+
+    # test IO when computation done in Python
+    cov.save('test-cov.fif')  # test saving
+    cov_read = Covariance('test-cov.fif')
+    assert_true(cov_read.ch_names == cov.ch_names)
+    assert_true(cov_read.nfree == cov.nfree)
+    assert_true((linalg.norm(cov.data - cov_read.data, ord='fro')
+            / linalg.norm(cov.data, ord='fro')) < 1e-5)
+
+
+def test_arithmetic_cov():
+    """Test arithmetic with noise covariance matrices
+    """
+    cov = Covariance(cov_fname)
+    cov_sum = cov + cov
+    assert_array_almost_equal(2 * cov.nfree, cov_sum.nfree)
+    assert_array_almost_equal(2 * cov.data, cov_sum.data)
+    assert_true(cov.ch_names == cov_sum.ch_names)
+
+    cov += cov
+    assert_array_almost_equal(cov_sum.nfree, cov.nfree)
+    assert_array_almost_equal(cov_sum.data, cov.data)
+    assert_true(cov_sum.ch_names == cov.ch_names)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/python-mne.git



More information about the debian-med-commit mailing list