Source code for pycartool.spi.source_space

# -*- coding: utf-8 -*-
# Authors: Victor Férat <victor.ferat@live.fr>
#
# License: BSD (3-clause)
import copy
import csv

import numpy as np


def _checkcoordinates(coordinates):
    if not isinstance(coordinates, np.ndarray):
        raise TypeError(f"coordinates must be a numpy array")
    if not coordinates.ndim == 2:
        raise ValueError(f"coordinates must have 2 dimension (ndim=2)")
    if not coordinates.shape[1] == 3:
        raise ValueError(
            f"coordinates must be of shape " f"(n_solutions_points, 3)"
        )
    return coordinates


def _checknames(names):
    if not isinstance(names, list):
        raise TypeError(f"names must be a list of string")
    return names


def _checksubject(subject):
    if subject is not None:
        if not isinstance(subject, str):
            raise ValueError(
                f"Subject must be a string but type "
                f"{type(subject)} was found."
            )
    return subject


[docs]def read_spi(filename, subject=None): """Create a SourceSpace instance from Cartool ``.spi`` file. Parameters ---------- filename : str or file-like The spi file to read. subject : str The subject used to create the source space. Returns ------- SourceSpace : pycartool.spi.SourceSpace The SourceSpace. """ with open(filename) as f: reader = csv.reader(f, delimiter="\t") d = list(reader) names = [elem[-1] for elem in d] coord = [elem[:-1] for elem in d] coord = np.array(coord) coord = coord.astype(float) Source_Space = SourceSpace( names, coord, filename=filename, subject=subject ) return Source_Space
[docs]def write_spi(filename, SourceSpace): """Write Cartool ``.spi`` file. Parameters ---------- filename : str or file-like The ``.spi`` file to write. SourceSpace : `pycartool.spi.SourceSpace` The SourceSpace to save. """ names = SourceSpace.names x, y, z = SourceSpace.coordinates.T with open(filename, "w", newline="") as f: writer = csv.writer(f, delimiter="\t") for s in enumerate(zip(x, y, z, names)): writer.writerow(s[1])
[docs]class SourceSpace(object): """Container for source space data. Parameters ---------- names : list of str The solutions point names. Length (``n_sources``). coordinates : `~numpy.ndarray` The solutions point names coordinates. Shape(n_sources, 3). subject : str Subject from who the source space was created. filename : str or file-like If loaded from a file, the corresponding filename. Attributes ---------- n_sources : int Number of sources. names : list of str The solutions point names. Length ``n_sources``. coordinates : `~numpy.array` The solutions point names coordinates. Shape(``n_sources``, ``3``) subject : str Subject from who the source space was created. filename : str or file-like If loaded from a file, the corresponding filename. """ def __init__(self, names, coordinates, subject=None, filename=None): _checkcoordinates(coordinates) _checknames(names) if not len(names) == coordinates.shape[0]: raise ValueError( f"coordinates and names dimensions must match" f" but found {len(names)} names and " f"{coordinates.shape[0]} solution points" f" coordinates" ) else: self.n_sources = len(names) self.subject = subject self.names = names self.coordinates = coordinates self.filename = filename def __repr__(self): # noqa: D401 """String representation.""" s = f"{self.n_sources} sources" if self.subject is not None: s += f", subject : {self.subject}" if self.filename is not None: s += f", filename : {self.filename}" return f"<SourceSpace or {s}>"
[docs] def get_coordinates(self): """Return a copy of sources coordinates. Returns ------- coordinates : `~numpy.array` The solutions point names coordinates. shape(``n_sources``, ``3``). """ return copy.deepcopy(self.coordinates)
[docs] def get_names(self): """Return a copy of sources names. Returns ------- names : list of str The solutions point names. Length ``n_sources``. """ return copy.deepcopy(self.names)
[docs] def save(self, filename): """Write SourceSpace to ``.spi`` file. Parameters ---------- filename : str or file-like The ``.spi`` file to write. """ write_spi(filename, self)
[docs] def get_center_of_mass(self, method="mean"): """Compute the center of mass of the Source Space. Parameters ---------- method : str The method to use. Can be 'mean', or 'median'. Returns ------- center_of_mass : `~numpy.array` The x,y,z coordinates of the center of mass. """ if method == "mean": center_of_mass = np.mean(self.coordinates, axis=0) elif method == "median": center_of_mass = np.median(self.coordinates, axis=0) return center_of_mass