File: matrix.py

package info (click to toggle)
python-mne 1.3.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 100,172 kB
  • sloc: python: 166,349; pascal: 3,602; javascript: 1,472; sh: 334; makefile: 236
file content (128 lines) | stat: -rw-r--r-- 4,435 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
# Authors: Alexandre Gramfort <alexandre.gramfort@inria.fr>
#          Matti Hämäläinen <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


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


def _read_named_matrix(fid, node, matkind, indent='    ', transpose=False):
    """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)s

    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)