Source code for pycartool.io.inverse_solution

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


[docs]def read_is(filename): """Read Cartool inverse solution (.is) file. Parameters ---------- filename : str the is file to read. Returns ------- ndarray, shape (n_regularizations, n_dim, n_solutionpoints, n_channels) the inverse solution matrices. n_dim=1 if solutions are scalar or n_dim=3 for vectorial solutions. """ with open(filename, 'rb') as f: print(f'Reading {filename}') print(f'Reading Header...') is_type = [struct.unpack('c', f.read(1))[0].decode('utf-8') for i in range(4)] is_type = ''.join(is_type) if is_type not in ['IS01', 'IS02', 'IS03']: print(f'{is_type} : Invalid IS type, please check that ' 'input file is a Inverse Solution matrix') raise ValueError print(f'IS type: {is_type}') n_channels = struct.unpack('I', f.read(4))[0] print(f'n_channels: {n_channels}') numsolutionpoints = struct.unpack('I', f.read(4))[0] print(f'n_solutionpoints: {numsolutionpoints}') numregularizations = struct.unpack('I', f.read(4))[0] print(f'n_regularizations: {numregularizations}') isinversescalar = struct.unpack('c', f.read(1))[0] if isinversescalar == '0': n_dim = 1 print(f'Inverse solution is Scalar') else: print(f'Inverse solution is Vectorial') n_dim = 3 if is_type in ['IS01', 'IS02']: buf = f.read(n_dim * numsolutionpoints * n_channel * 4) data = np.frombuffer(buf, dtype=np.float32) data = data.reshape(ndim, numsolutionpoints, n_channel) data = no.array([data]) elif is_type == 'IS03': print(f"Reading Variable Header...") ch_names = [] for _ in range(n_channels): name = [char for char in f.read(32).split(b'\x00') if char != b''][0] ch_names.append(name.decode('utf-8')) solutionpoints_names = [] for _ in range(numsolutionpoints): name = [char for char in f.read(16).split(b'\x00') if char != b''][0] solutionpoints_names.append(name.decode('utf-8')) regularizations_values = [] for _ in range(numregularizations): value = struct.unpack('d', f.read(8))[0] regularizations_values.append(value) print(f'Regularizations values: {regularizations_values}') regularizations_names = [] for _ in range(numregularizations): name = [char for char in f.read(32).split(b'\x00') if char != b''][0] regularizations_names.append(name.decode('utf-8')) print(f'Regularizations names: {regularizations_names}') regularisation_solutions = [] buf = f.read(numregularizations * n_dim * numsolutionpoints * n_channels * 4) data = np.frombuffer(buf, dtype=np.float32) data = data.reshape(numregularizations, n_dim, numsolutionpoints, n_channels) regularisation_solutions = np.array(regularisation_solutions) inverse_solution = {'is_type': is_type, 'is_scalar': True if isinversescalar == "0" else False, 'ch_names': ch_names, 'solutionpoints_names': solutionpoints_names, 'regularizations_values': regularizations_values, 'regularizations_names': regularizations_names, 'regularisation_solutions': data} return(inverse_solution)
[docs]def read_ris(filename): """Read Cartool Results of Inverse Solution computation (.ris) file. Parameters ---------- filename : str the ris file to read. Returns ------- results_of_is : dict of str Keys are: ris_type : str magic should always be 'RI01'. is_scalar : bool True if solution is scalar, else False (vectorial). sfreq : float sampling frequency (in Hz). data : np.ndarray, shape(n_timeframes, n_dim, n_solutionpoints) time course of each solution point. """ with open(filename, 'rb') as f: print(f'Reading {filename}') print(f'Reading Header...') ris_type = [struct.unpack('c', f.read(1))[0].decode('utf-8') for i in range(4)] ris_type = ''.join(ris_type) if ris_type not in ["RI01"]: raise ValueError(f'{ris_type} : Invalid RI type, please check that' f' input file is a Result of Inverse Solution ' f' computation') print(f'IS type: {ris_type}') n_solutionpoints = struct.unpack('I', f.read(4))[0] print(f'n_solutionpoints: {n_solutionpoints}') n_timeframes = struct.unpack('I', f.read(4))[0] print(f'n_timeframes: {n_timeframes}') s_freq = struct.unpack('f', f.read(4))[0] print(f'Samplimg frequency: {s_freq}') isinversescalar = struct.unpack('c', f.read(1))[0] if isinversescalar == '0': n_dim = 1 print(f'Result of Inverse Solution computation is Scalar') else: print(f'Result of Inverse Solution computation is Vectorial') n_dim = 3 buf = f.read(n_dim * n_solutionpoints * n_timeframes * 4) data = np.frombuffer(buf, dtype=np.float32) data = data.reshape(n_timeframes, n_dim, n_solutionpoints) results_of_is = {'ris_type': ris_type, 'is_scalar': True if isinversescalar == '0' else False, 'sfreq': s_freq, 'data': data} return(results_of_is)
[docs]def write_ris(path, data, sfreq): """Short summary. Parameters ---------- path : str Path of the exported inverse solution computation. data : np.ndarray, shape(n_timeframes, n_dim, n_solutionpoints) time course of each solution point. sfreq : float sampling frequency (in Hz). """ if not isinstance(data, np.ndarray): raise TypeError('Input data must be a ndarray') if data.ndim != 3: raise ValueError('Input data must be a 3D array') if data.shape[1] == 1: isinversescalar = '0' elif data.shape[1] == 3: isinversescalar = '1' else: raise ValueError('Input data must have shape (_,1,_) (scalar)' ' or (_,3,_) (vectorial)') ris_type = 'RI01' n_timeframes = data.shape[0] n_solutionpoints = data.shape[2] f = open(path, 'wb') f.write(ris_type.encode('utf-8')) f.write(struct.pack('I', n_solutionpoints)) f.write(struct.pack('I', n_timeframes)) f.write(struct.pack('f', sfreq)) f.write(isinversescalar.encode('utf-8')) data = data.astype(np.float32) data.tofile(f) f.close()