File: matrix.py

package info (click to toggle)
python-mne 0.17%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 95,104 kB
  • sloc: python: 110,639; makefile: 222; sh: 15
file content (132 lines) | stat: -rw-r--r-- 4,666 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# Authors: Alexandre Gramfort <alexandre.gramfort@telecom-paristech.fr>
#          Matti Hamalainen <msh@nmr.mgh.harvard.edu>
#
# License: BSD (3-clause)

from .constants import FIFF
from .tag import find_tag, has_tag
from .write import (write_int, start_block, end_block, write_float_matrix,
                    write_name_list)
from ..utils import logger, verbose


def _transpose_named_matrix(mat):
    """Transpose mat inplace (no copy)."""
    mat['nrow'], mat['ncol'] = mat['ncol'], mat['nrow']
    mat['row_names'], mat['col_names'] = mat['col_names'], mat['row_names']
    mat['data'] = mat['data'].T


@verbose
def _read_named_matrix(fid, node, matkind, indent='    ', transpose=False,
                       verbose=None):
    """Read named matrix from the given node.

    Parameters
    ----------
    fid : file
        The opened file descriptor.
    node : dict
        The node in the tree.
    matkind : int
        The type of matrix.
    transpose : bool
        If True, transpose the matrix. Default is False.
    verbose : bool, str, int, or None
        If not None, override default verbose level (see :func:`mne.verbose`
        and :ref:`Logging documentation <tut_logging>` for more).

    Returns
    -------
    mat: dict
        The matrix data
    """
    #   Descend one level if necessary
    if node['block'] != FIFF.FIFFB_MNE_NAMED_MATRIX:
        for k in range(node['nchild']):
            if node['children'][k]['block'] == FIFF.FIFFB_MNE_NAMED_MATRIX:
                if has_tag(node['children'][k], matkind):
                    node = node['children'][k]
                    break
        else:
            logger.info(indent + 'Desired named matrix (kind = %d) not '
                        'available' % matkind)
            return None
    else:
        if not has_tag(node, matkind):
            logger.info(indent + 'Desired named matrix (kind = %d) not '
                        'available' % matkind)
            return None

    #   Read everything we need
    tag = find_tag(fid, node, matkind)
    if tag is None:
        raise ValueError('Matrix data missing')
    else:
        data = tag.data

    nrow, ncol = data.shape
    tag = find_tag(fid, node, FIFF.FIFF_MNE_NROW)
    if tag is not None and tag.data != nrow:
        raise ValueError('Number of rows in matrix data and FIFF_MNE_NROW '
                         'tag do not match')

    tag = find_tag(fid, node, FIFF.FIFF_MNE_NCOL)
    if tag is not None and tag.data != ncol:
        raise ValueError('Number of columns in matrix data and '
                         'FIFF_MNE_NCOL tag do not match')

    tag = find_tag(fid, node, FIFF.FIFF_MNE_ROW_NAMES)
    row_names = tag.data.split(':') if tag is not None else []

    tag = find_tag(fid, node, FIFF.FIFF_MNE_COL_NAMES)
    col_names = tag.data.split(':') if tag is not None else []

    mat = dict(nrow=nrow, ncol=ncol, row_names=row_names, col_names=col_names,
               data=data)
    if transpose:
        _transpose_named_matrix(mat)
    return mat


def write_named_matrix(fid, kind, mat):
    """Write named matrix from the given node.

    Parameters
    ----------
    fid : file
        The opened file descriptor.
    kind : int
        The kind of the matrix.
    matkind : int
        The type of matrix.
    """
    # let's save ourselves from disaster
    n_tot = mat['nrow'] * mat['ncol']
    if mat['data'].size != n_tot:
        ratio = n_tot / float(mat['data'].size)
        if n_tot < mat['data'].size and ratio > 0:
            ratio = 1 / ratio
        raise ValueError('Cannot write matrix: row (%i) and column (%i) '
                         'total element (%i) mismatch with data size (%i), '
                         'appears to be off by a factor of %gx'
                         % (mat['nrow'], mat['ncol'], n_tot,
                            mat['data'].size, ratio))
    start_block(fid, FIFF.FIFFB_MNE_NAMED_MATRIX)
    write_int(fid, FIFF.FIFF_MNE_NROW, mat['nrow'])
    write_int(fid, FIFF.FIFF_MNE_NCOL, mat['ncol'])

    if len(mat['row_names']) > 0:
        # let's prevent unintentional stupidity
        if len(mat['row_names']) != mat['nrow']:
            raise ValueError('len(mat["row_names"]) != mat["nrow"]')
        write_name_list(fid, FIFF.FIFF_MNE_ROW_NAMES, mat['row_names'])

    if len(mat['col_names']) > 0:
        # let's prevent unintentional stupidity
        if len(mat['col_names']) != mat['ncol']:
            raise ValueError('len(mat["col_names"]) != mat["ncol"]')
        write_name_list(fid, FIFF.FIFF_MNE_COL_NAMES, mat['col_names'])

    write_float_matrix(fid, kind, mat['data'])
    end_block(fid, FIFF.FIFFB_MNE_NAMED_MATRIX)