This is an automated email from the git hooks/post-receive script. yoh pushed a commit to annotated tag v0.1 in repository python-mne.
commit d0b2b37c84572114727ae03804d29d8238c4037f Author: Alexandre Gramfort <[email protected]> Date: Sun Dec 26 19:43:04 2010 -0500 intial commit --- examples/read_ave.py | 4 + fiff/__init__.py | 2 + fiff/bunch.py | 9 ++ fiff/constants.py | 365 +++++++++++++++++++++++++++++++++++++++++++++++++++ fiff/open.py | 59 +++++++++ fiff/read_tag.py | 185 ++++++++++++++++++++++++++ fiff/tree.py | 85 ++++++++++++ setup.py | 0 8 files changed, 709 insertions(+) diff --git a/examples/read_ave.py b/examples/read_ave.py new file mode 100644 index 0000000..4ced76f --- /dev/null +++ b/examples/read_ave.py @@ -0,0 +1,4 @@ +import fiff + +fname = 'sm02a1-ave.fif' +fid, tree, directory = fiff.fiff_open(fname, verbose=True) diff --git a/fiff/__init__.py b/fiff/__init__.py new file mode 100644 index 0000000..3d30a6e --- /dev/null +++ b/fiff/__init__.py @@ -0,0 +1,2 @@ +from .open import fiff_open +from .constants import FIFF diff --git a/fiff/bunch.py b/fiff/bunch.py new file mode 100644 index 0000000..e26affb --- /dev/null +++ b/fiff/bunch.py @@ -0,0 +1,9 @@ +class Bunch(dict): + """ Container object for datasets: dictionnary-like object that + exposes its keys as attributes. + """ + + def __init__(self, **kwargs): + dict.__init__(self, kwargs) + self.__dict__ = self + diff --git a/fiff/constants.py b/fiff/constants.py new file mode 100644 index 0000000..93f508b --- /dev/null +++ b/fiff/constants.py @@ -0,0 +1,365 @@ +from bunch import Bunch + +FIFF = Bunch() + +# +# Blocks +# +FIFF.FIFFB_MEAS = 100; +FIFF.FIFFB_MEAS_INFO = 101; +FIFF.FIFFB_RAW_DATA = 102; +FIFF.FIFFB_PROCESSED_DATA = 103; +FIFF.FIFFB_CONTINUOUS_DATA = 112; +FIFF.FIFFB_EVOKED = 104; +FIFF.FIFFB_ASPECT = 105; +FIFF.FIFFB_SUBJECT = 106; +FIFF.FIFFB_ISOTRAK = 107; +FIFF.FIFFB_HPI_MEAS = 108; +FIFF.FIFFB_HPI_RESULT = 109; +FIFF.FIFFB_DACQ_PARS = 117; +FIFF.FIFFB_REF = 118; +FIFF.FIFFB_SMSH_RAW_DATA = 119; +FIFF.FIFFB_SMSH_ASPECT = 120; +FIFF.FIFFB_PROJ = 313; +FIFF.FIFFB_PROJ_ITEM = 314; +FIFF.FIFFB_MRI = 200; +FIFF.FIFFB_MRI_SET = 201; +FIFF.FIFFB_MRI_SLICE = 202; +FIFF.FIFFB_PROCESSING_HISTORY = 900; +FIFF.FIFFB_SSS_INFO = 502; +FIFF.FIFFB_SSS_CAL_ADJUST = 503; +FIFF.FIFFB_SSS_ST_INFO = 504; +FIFF.FIFFB_SSS_BASES = 505; +# +# Of general interest +# +FIFF.FIFF_FILE_ID = 100; +FIFF.FIFF_DIR_POINTER = 101; +FIFF.FIFF_BLOCK_ID = 103; +FIFF.FIFF_BLOCK_START = 104; +FIFF.FIFF_BLOCK_END = 105; +FIFF.FIFF_FREE_LIST = 106; +FIFF.FIFF_FREE_BLOCK = 107; +FIFF.FIFF_NOP = 108; +FIFF.FIFF_PARENT_FILE_ID = 109; +FIFF.FIFF_PARENT_BLOCK_ID = 110; +# +# Megacq saves the parameters in these tags +# +FIFF.FIFF_DACQ_PARS = 150; +FIFF.FIFF_DACQ_STIM = 151; + +FIFF.FIFF_SFREQ = 201; +FIFF.FIFF_NCHAN = 200; +FIFF.FIFF_DATA_PACK = 202; +FIFF.FIFF_CH_INFO = 203; +FIFF.FIFF_MEAS_DATE = 204; +FIFF.FIFF_SUBJECT = 205; +FIFF.FIFF_COMMENT = 206; +FIFF.FIFF_NAVE = 207; +FIFF.FIFF_DIG_POINT = 213; +FIFF.FIFF_LOWPASS = 219; +FIFF.FIFF_COORD_TRANS = 222; +FIFF.FIFF_HIGHPASS = 223; +FIFF.FIFF_NAME = 233; +FIFF.FIFF_DESCRIPTION = FIFF.FIFF_COMMENT; +# +# Pointers +# +FIFF.FIFFV_NEXT_SEQ = 0; +FIFF.FIFFV_NEXT_NONE = -1; +# +# Channel types +# +FIFF.FIFFV_MEG_CH = 1; +FIFF.FIFFV_REF_MEG_CH = 301; +FIFF.FIFFV_EEG_CH = 2; +FIFF.FIFFV_MCG_CH = 201; +FIFF.FIFFV_STIM_CH = 3; +FIFF.FIFFV_EOG_CH = 202; +FIFF.FIFFV_EMG_CH = 302; +FIFF.FIFFV_ECG_CH = 402; +FIFF.FIFFV_MISC_CH = 502; +FIFF.FIFFV_RESP_CH = 602; # Respiration monitoring +# +# Quaternion channels for head position monitoring +# +FIFF.FIFFV_QUAT_0 = 700; # Quaternion parameter q0; obsolete for unit quaternion +FIFF.FIFFV_QUAT_1 = 701; # Quaternion parameter q1; rotation +FIFF.FIFFV_QUAT_2 = 702; # Quaternion parameter q2; rotation +FIFF.FIFFV_QUAT_3 = 703; # Quaternion parameter q3; rotation +FIFF.FIFFV_QUAT_4 = 704; # Quaternion parameter q4; translation +FIFF.FIFFV_QUAT_5 = 705; # Quaternion parameter q5; translation +FIFF.FIFFV_QUAT_6 = 706; # Quaternion parameter q6; translation +FIFF.FIFFV_HPI_G = 707; # Goodness-of-fit in continuous hpi +FIFF.FIFFV_HPI_ERR = 708; # Estimation error in continuous hpi +FIFF.FIFFV_HPI_MOV = 709; # Estimated head movement speed in continuous hpi +# +# Coordinate frames +# +FIFF.FIFFV_COORD_UNKNOWN = 0; +FIFF.FIFFV_COORD_DEVICE = 1; +FIFF.FIFFV_COORD_ISOTRAK = 2; +FIFF.FIFFV_COORD_HPI = 3; +FIFF.FIFFV_COORD_HEAD = 4; +FIFF.FIFFV_COORD_MRI = 5; +FIFF.FIFFV_COORD_MRI_SLICE = 6; +FIFF.FIFFV_COORD_MRI_DISPLAY = 7; +FIFF.FIFFV_COORD_DICOM_DEVICE = 8; +FIFF.FIFFV_COORD_IMAGING_DEVICE = 9; +# +# Needed for raw and evoked-response data +# +FIFF.FIFF_FIRST_SAMPLE = 208; +FIFF.FIFF_LAST_SAMPLE = 209; +FIFF.FIFF_ASPECT_KIND = 210; +FIFF.FIFF_DATA_BUFFER = 300; # Buffer containing measurement data +FIFF.FIFF_DATA_SKIP = 301; # Data skip in buffers +FIFF.FIFF_EPOCH = 302; # Buffer containing one epoch and channel +FIFF.FIFF_DATA_SKIP_SAMP = 303; # Data skip in samples + +# +# Different aspects of data +# +FIFF.FIFFV_ASPECT_AVERAGE = 100; # Normal average of epochs +FIFF.FIFFV_ASPECT_STD_ERR = 101; # Std. error of mean +FIFF.FIFFV_ASPECT_SINGLE = 102; # Single epoch cut out from the continuous data +FIFF.FIFFV_ASPECT_SUBAVERAGE = 103; +FIFF.FIFFV_ASPECT_ALTAVERAGE = 104; # Alternating subaverage +FIFF.FIFFV_ASPECT_SAMPLE = 105; # A sample cut out by graph +FIFF.FIFFV_ASPECT_POWER_DENSITY = 106; # Power density spectrum +FIFF.FIFFV_ASPECT_DIPOLE_WAVE = 200; # Dipole amplitude curve +# +# BEM surface IDs +# +FIFF.FIFFV_BEM_SURF_ID_UNKNOWN = -1; +FIFF.FIFFV_BEM_SURF_ID_BRAIN = 1; +FIFF.FIFFV_BEM_SURF_ID_SKULL = 3; +FIFF.FIFFV_BEM_SURF_ID_HEAD = 4; +# +# More of those defined in MNE +# +FIFF.FIFFV_MNE_SURF_UNKNOWN = -1; +FIFF.FIFFV_MNE_SURF_LEFT_HEMI = 101; +FIFF.FIFFV_MNE_SURF_RIGHT_HEMI = 102; +# +# These relate to the Isotrak data +# +FIFF.FIFFV_POINT_CARDINAL = 1; +FIFF.FIFFV_POINT_HPI = 2; +FIFF.FIFFV_POINT_EEG = 3; +FIFF.FIFFV_POINT_ECG = FIFF.FIFFV_POINT_EEG; +FIFF.FIFFV_POINT_EXTRA = 4; + +FIFF.FIFFV_POINT_LPA=1; +FIFF.FIFFV_POINT_NASION=2; +FIFF.FIFFV_POINT_RPA=3; +# +# SSP +# +FIFF.FIFF_PROJ_ITEM_KIND = 3411; +FIFF.FIFF_PROJ_ITEM_TIME = 3412; +FIFF.FIFF_PROJ_ITEM_NVEC = 3414; +FIFF.FIFF_PROJ_ITEM_VECTORS = 3415; +FIFF.FIFF_PROJ_ITEM_CH_NAME_LIST = 3417; +# +# MRIs +# +FIFF.FIFF_MRI_SOURCE_PATH = 1101; +FIFF.FIFF_MRI_SOURCE_FORMAT = 2002; +FIFF.FIFF_MRI_PIXEL_ENCODING = 2003; +FIFF.FIFF_MRI_PIXEL_DATA_OFFSET = 2004; +FIFF.FIFF_MRI_PIXEL_SCALE = 2005; +FIFF.FIFF_MRI_PIXEL_DATA = 2006; +FIFF.FIFF_MRI_WIDTH = 2010; +FIFF.FIFF_MRI_WIDTH_M = 2011; +FIFF.FIFF_MRI_HEIGHT = 2012; +FIFF.FIFF_MRI_HEIGHT_M = 2013; +# +FIFF.FIFFV_MRI_PIXEL_BYTE = 1; +FIFF.FIFFV_MRI_PIXEL_WORD = 2; +FIFF.FIFFV_MRI_PIXEL_SWAP_WORD = 3; +FIFF.FIFFV_MRI_PIXEL_FLOAT = 4; +# +# These are the MNE fiff definitions +# +FIFF.FIFFB_MNE = 350; +FIFF.FIFFB_MNE_SOURCE_SPACE = 351; +FIFF.FIFFB_MNE_FORWARD_SOLUTION = 352; +FIFF.FIFFB_MNE_PARENT_MRI_FILE = 353; +FIFF.FIFFB_MNE_PARENT_MEAS_FILE = 354; +FIFF.FIFFB_MNE_COV = 355; +FIFF.FIFFB_MNE_INVERSE_SOLUTION = 356; +FIFF.FIFFB_MNE_NAMED_MATRIX = 357; +FIFF.FIFFB_MNE_ENV = 358; +FIFF.FIFFB_MNE_BAD_CHANNELS = 359; +FIFF.FIFFB_MNE_VERTEX_MAP = 360; +FIFF.FIFFB_MNE_EVENTS = 361; +FIFF.FIFFB_MNE_MORPH_MAP = 362; +# +# CTF compensation data +# +FIFF.FIFFB_MNE_CTF_COMP = 370; +FIFF.FIFFB_MNE_CTF_COMP_DATA = 371; +# +# Fiff tags associated with MNE computations (3500...) +# +# +# 3500... Bookkeeping +# +FIFF.FIFF_MNE_ROW_NAMES = 3502; +FIFF.FIFF_MNE_COL_NAMES = 3503; +FIFF.FIFF_MNE_NROW = 3504; +FIFF.FIFF_MNE_NCOL = 3505; +FIFF.FIFF_MNE_COORD_FRAME = 3506; # Coordinate frame employed. Defaults: + # FIFFB_MNE_SOURCE_SPACE FIFFV_COORD_MRI + # FIFFB_MNE_FORWARD_SOLUTION FIFFV_COORD_HEAD + # FIFFB_MNE_INVERSE_SOLUTION FIFFV_COORD_HEAD +FIFF.FIFF_MNE_CH_NAME_LIST = 3507; +FIFF.FIFF_MNE_FILE_NAME = 3508; # This removes the collision with fiff_file.h (used to be 3501) +# +# 3510... 3590... Source space or surface +# +FIFF.FIFF_MNE_SOURCE_SPACE_POINTS = 3510; # The vertices +FIFF.FIFF_MNE_SOURCE_SPACE_NORMALS = 3511; # The vertex normals +FIFF.FIFF_MNE_SOURCE_SPACE_NPOINTS = 3512; # How many vertices +FIFF.FIFF_MNE_SOURCE_SPACE_SELECTION = 3513; # Which are selected to the source space +FIFF.FIFF_MNE_SOURCE_SPACE_NUSE = 3514; # How many are in use +FIFF.FIFF_MNE_SOURCE_SPACE_NEAREST = 3515; # Nearest source space vertex for all vertices +FIFF.FIFF_MNE_SOURCE_SPACE_NEAREST_DIST = 3516; # Distance to the Nearest source space vertex for all vertices +FIFF.FIFF_MNE_SOURCE_SPACE_ID = 3517; # Identifier + +FIFF.FIFF_MNE_SOURCE_SPACE_NTRI = 3590; # Number of triangles +FIFF.FIFF_MNE_SOURCE_SPACE_TRIANGLES = 3591; # The triangulation +FIFF.FIFF_MNE_SOURCE_SPACE_NUSE_TRI = 3592; # Number of triangles corresponding to the number of vertices in use +FIFF.FIFF_MNE_SOURCE_SPACE_USE_TRIANGLES = 3593; # The triangulation of the used vertices in the source space +# +# 3520... Forward solution +# +FIFF.FIFF_MNE_FORWARD_SOLUTION = 3520; +FIFF.FIFF_MNE_SOURCE_ORIENTATION = 3521; # Fixed or free +FIFF.FIFF_MNE_INCLUDED_METHODS = 3522; +FIFF.FIFF_MNE_FORWARD_SOLUTION_GRAD = 3523; +# +# 3530... Covariance matrix +# +FIFF.FIFF_MNE_COV_KIND = 3530; # What kind of a covariance matrix +FIFF.FIFF_MNE_COV_DIM = 3531; # Matrix dimension +FIFF.FIFF_MNE_COV = 3532; # Full matrix in packed representation (lower triangle) +FIFF.FIFF_MNE_COV_DIAG = 3533; # Diagonal matrix +FIFF.FIFF_MNE_COV_EIGENVALUES = 3534; # Eigenvalues and eigenvectors of the above +FIFF.FIFF_MNE_COV_EIGENVECTORS = 3535; +FIFF.FIFF_MNE_COV_NFREE = 3536; # Number of degrees of freedom +# +# 3540... Inverse operator +# +# We store the inverse operator as the eigenleads, eigenfields, +# and weights +# +FIFF.FIFF_MNE_INVERSE_LEADS = 3540; # The eigenleads +FIFF.FIFF_MNE_INVERSE_LEADS_WEIGHTED = 3546; # The eigenleads (already weighted with R^0.5) +FIFF.FIFF_MNE_INVERSE_FIELDS = 3541; # The eigenfields +FIFF.FIFF_MNE_INVERSE_SING = 3542; # The singular values +FIFF.FIFF_MNE_PRIORS_USED = 3543; # Which kind of priors have been used for the source covariance matrix +FIFF.FIFF_MNE_INVERSE_FULL = 3544; # Inverse operator as one matrix + # This matrix includes the whitening operator as well + # The regularization is applied +FIFF.FIFF_MNE_INVERSE_SOURCE_ORIENTATIONS = 3545; # Contains the orientation of one source per row + # The source orientations must be expressed in the coordinate system + # given by FIFF_MNE_COORD_FRAME +# +# 3550... Saved environment info +# +FIFF.FIFF_MNE_ENV_WORKING_DIR = 3550; # Working directory where the file was created +FIFF.FIFF_MNE_ENV_COMMAND_LINE = 3551; # The command used to create the file +# +# 3560... Miscellaneous +# +FIFF.FIFF_MNE_PROJ_ITEM_ACTIVE = 3560; # Is this projection item active? +FIFF.FIFF_MNE_EVENT_LIST = 3561; # An event list (for STI 014) +FIFF.FIFF_MNE_HEMI = 3562; # Hemisphere association for general purposes +# +# 3570... Morphing maps +# +FIFF.FIFF_MNE_MORPH_MAP = 3570; # Mapping of closest vertices on the sphere +FIFF.FIFF_MNE_MORPH_MAP_FROM = 3571; # Which subject is this map from +FIFF.FIFF_MNE_MORPH_MAP_TO = 3572; # Which subject is this map to +# +# 3580... CTF compensation data +# +FIFF.FIFF_MNE_CTF_COMP_KIND = 3580; # What kind of compensation +FIFF.FIFF_MNE_CTF_COMP_DATA = 3581; # The compensation data itself +FIFF.FIFF_MNE_CTF_COMP_CALIBRATED = 3582; # Are the coefficients calibrated? +# +# Fiff values associated with MNE computations +# +FIFF.FIFFV_MNE_FIXED_ORI = 1; +FIFF.FIFFV_MNE_FREE_ORI = 2; + +FIFF.FIFFV_MNE_MEG = 1; +FIFF.FIFFV_MNE_EEG = 2; +FIFF.FIFFV_MNE_MEG_EEG = 3; + +FIFF.FIFFV_MNE_UNKNOWN_COV = 0; +FIFF.FIFFV_MNE_SENSOR_COV = 1; +FIFF.FIFFV_MNE_NOISE_COV = 1; # This is what it should have been called +FIFF.FIFFV_MNE_SOURCE_COV = 2; +FIFF.FIFFV_MNE_FMRI_PRIOR_COV = 3; +FIFF.FIFFV_MNE_SIGNAL_COV = 4; # This will be potentially employed in beamformers +FIFF.FIFFV_MNE_DEPTH_PRIOR_COV = 5; # The depth weighting prior +FIFF.FIFFV_MNE_ORIENT_PRIOR_COV = 6; # The orientation prior +# +# Projection item kinds +# +FIFF.FIFFV_PROJ_ITEM_NONE = 0; +FIFF.FIFFV_PROJ_ITEM_FIELD = 1; +FIFF.FIFFV_PROJ_ITEM_DIP_FIX = 2; +FIFF.FIFFV_PROJ_ITEM_DIP_ROT = 3; +FIFF.FIFFV_PROJ_ITEM_HOMOG_GRAD = 4; +FIFF.FIFFV_PROJ_ITEM_HOMOG_FIELD = 5; +FIFF.FIFFV_MNE_PROJ_ITEM_EEG_AVREF = 10; +# +# Additional coordinate frames +# +FIFF.FIFFV_MNE_COORD_TUFTS_EEG = 300; # For Tufts EEG data +FIFF.FIFFV_MNE_COORD_CTF_DEVICE = 1001; # CTF device coordinates +FIFF.FIFFV_MNE_COORD_CTF_HEAD = 1004; # CTF head coordinates +FIFF.FIFFV_MNE_COORD_MRI_VOXEL = 2001; # The MRI voxel coordinates +FIFF.FIFFV_MNE_COORD_RAS = 2002; # Surface RAS coordinates with non-zero origin +FIFF.FIFFV_MNE_COORD_MNI_TAL = 2003; # MNI Talairach coordinates +FIFF.FIFFV_MNE_COORD_FS_TAL_GTZ = 2004; # FreeSurfer Talairach coordinates (MNI z > 0) +FIFF.FIFFV_MNE_COORD_FS_TAL_LTZ = 2005; # FreeSurfer Talairach coordinates (MNI z < 0) +FIFF.FIFFV_MNE_COORD_FS_TAL = 2006; # FreeSurfer Talairach coordinates +# +# CTF coil and channel types +# +FIFF.FIFFV_REF_MEG_CH = 301; +# +# Data types +# +FIFF.FIFFT_VOID = 0; +FIFF.FIFFT_BYTE = 1; +FIFF.FIFFT_SHORT = 2; +FIFF.FIFFT_INT = 3; +FIFF.FIFFT_FLOAT = 4; +FIFF.FIFFT_DOUBLE = 5; +FIFF.FIFFT_JULIAN = 6; +FIFF.FIFFT_USHORT = 7; +FIFF.FIFFT_UINT = 8; +FIFF.FIFFT_ULONG = 9; +FIFF.FIFFT_STRING = 10; +FIFF.FIFFT_LONG = 11; +FIFF.FIFFT_DAU_PACK13 = 13; +FIFF.FIFFT_DAU_PACK14 = 14; +FIFF.FIFFT_DAU_PACK16 = 16; +FIFF.FIFFT_COMPLEX_FLOAT = 20; +FIFF.FIFFT_COMPLEX_DOUBLE = 21; +FIFF.FIFFT_OLD_PACK = 23; +FIFF.FIFFT_CH_INFO_STRUCT = 30; +FIFF.FIFFT_ID_STRUCT = 31; +FIFF.FIFFT_DIR_ENTRY_STRUCT = 32; +FIFF.FIFFT_DIG_POINT_STRUCT = 33; +FIFF.FIFFT_CH_POS_STRUCT = 34; +FIFF.FIFFT_COORD_TRANS_STRUCT = 35; +FIFF.FIFFT_DIG_STRING_STRUCT = 36; +FIFF.FIFFT_STREAM_SEGMENT_STRUCT = 37; diff --git a/fiff/open.py b/fiff/open.py new file mode 100644 index 0000000..515fc49 --- /dev/null +++ b/fiff/open.py @@ -0,0 +1,59 @@ +import struct +import numpy as np + +from .read_tag import read_tag_info, read_tag +from .tree import make_dir_tree +from .constants import FIFF + +def fiff_open(fname, verbose=False): + + fid = open(fname, "rb") # Open in binary mode + + tag = read_tag_info(fid) + + # + # Check that this looks like a fif file + # + if tag.kind != FIFF.FIFF_FILE_ID: + raise ValueError, 'file does not start with a file id tag' + + if tag.type != FIFF.FIFFT_ID_STRUCT: + raise ValueError, 'file does not start with a file id tag' + + if tag.size != 20: + raise ValueError, 'file does not start with a file id tag' + + tag = read_tag(fid) + + if tag.kind != FIFF.FIFF_DIR_POINTER: + raise ValueError, 'file does have a directory pointer' + + # + # Read or create the directory tree + # + if verbose: + print '\tCreating tag directory for %s...' % fname + + dirpos = int(tag.data) + if dirpos > 0: + tag = read_tag(fid, dirpos) + directory = tag.data + else: + fid.seek(0, 0) + directory = list() + while tag.next >= 0: + pos = fid.tell() + directory.append(read_tag_info(fid)) + + tree = make_dir_tree(fid, directory) + + if verbose: + print '[done]\n' + + # + # Back to the beginning + # + fid.seek(0) + # fid.close() + + return fid, tree, directory diff --git a/fiff/read_tag.py b/fiff/read_tag.py new file mode 100644 index 0000000..700500d --- /dev/null +++ b/fiff/read_tag.py @@ -0,0 +1,185 @@ +import struct +import numpy as np + +from .bunch import Bunch +from .constants import FIFF + +class Tag(object): + """docstring for Tag""" + def __init__(self, kind, type, size, next): + self.kind = kind + self.type = type + self.size = size + self.next = next + + def __repr__(self): + out = "kind: %s - type: %s - size: %s - next: %s" % ( + self.kind, self.type, self.size, self.next) + if hasattr(self, 'data'): + out += " - data: %s\n" % self.data + else: + out += "\n" + return out + + @property + def pos(self): + return self.next + +def read_tag_info(fid): + s = fid.read(4*4) + tag = Tag(*struct.unpack(">iiii", s)) + if tag.next == 0: + fid.seek(tag.size, 1) + else: + fid.seek(tag.next, 0) + return tag + + +def read_tag(fid, pos=None): + if pos is not None: + fid.seek(pos, 0) + + s = fid.read(4*4) + tag = Tag(*struct.unpack(">iIii", s)) + + # + # The magic hexadecimal values + # + is_matrix = 4294901760 # ffff0000 + matrix_coding_dense = 16384 # 4000 + matrix_coding_CCS = 16400 # 4010 + matrix_coding_RCS = 16416 # 4020 + data_type = 65535 # ffff + # + if tag.size > 0: + matrix_coding = is_matrix & tag.type + if matrix_coding != 0: + raise ValueError, "matrix_coding not implemented" + # XXX : todo + pass + else: + # All other data types + + # Simple types + + if tag.type == FIFF.FIFFT_BYTE: + tag.data = np.fromfile(fid, dtype=">B1", count=tag.size) + elif tag.type == FIFF.FIFFT_SHORT: + tag.data = np.fromfile(fid, dtype=">h2", count=tag.size/2) + elif tag.type == FIFF.FIFFT_INT: + tag.data = np.fromfile(fid, dtype=">i4", count=tag.size/4) + elif tag.type == FIFF.FIFFT_USHORT: + tag.data = np.fromfile(fid, dtype=">H2", count=tag.size/2) + elif tag.type == FIFF.FIFFT_UINT: + tag.data = np.fromfile(fid, dtype=">I4", count=tag.size/4) + elif tag.type == FIFF.FIFFT_FLOAT: + tag.data = np.fromfile(fid, dtype=">f4", count=tag.size/4) + elif tag.type == FIFF.FIFFT_DOUBLE: + tag.data = np.fromfile(fid, dtype=">f8", count=tag.size/8) + elif tag.type == FIFF.FIFFT_STRING: + tag.data = np.fromfile(fid, dtype=">c1", count=tag.size) + elif tag.type == FIFF.FIFFT_DAU_PACK16: + tag.data = np.fromfile(fid, dtype=">h2", count=tag.size/2) + elif tag.type == FIFF.FIFFT_COMPLEX_FLOAT: + tag.data = np.fromfile(fid, dtype=">f4", count=tag.size/4) + tag.data = tag.data[::2] + 1j * tag.data[1::2] + elif tag.type == FIFF.FIFFT_COMPLEX_DOUBLE: + tag.data = np.fromfile(fid, dtype=">f8", count=tag.size/8) + tag.data = tag.data[::2] + 1j * tag.data[1::2] + # + # Structures + # + elif tag.type == FIFF.FIFFT_ID_STRUCT: + tag.data = dict() + tag.data['version'] = np.fromfile(fid, dtype=">i4", count=1) + tag.data['version'] = np.fromfile(fid, dtype=">i4", count=1) + tag.data['machid'] = np.fromfile(fid, dtype=">i4", count=2) + tag.data['secs'] = np.fromfile(fid, dtype=">i4", count=1) + tag.data['usecs'] = np.fromfile(fid, dtype=">i4", count=1) + elif tag.type == FIFF.FIFFT_DIG_POINT_STRUCT: + tag.data = dict() + tag.data['kind'] = np.fromfile(fid, dtype=">i4", count=1) + tag.data['ident'] = np.fromfile(fid, dtype=">i4", count=1) + tag.data['r'] = np.fromfile(fid, dtype=">i4", count=3) + tag.data['coord_frame'] = 0 + elif tag.type == FIFF.FIFFT_COORD_TRANS_STRUCT: + tag.data = Bunch() + tag.data['from'] = np.fromfile(fid, dtype=">i4", count=1) + tag.data['to'] = np.fromfile(fid, dtype=">i4", count=1) + rot = np.fromfile(fid, dtype=">f4", count=9).reshape(3, 3) + move = np.fromfile(fid, dtype=">f4", count=3) + tag.data['trans'] = np.r_[ np.c_[rot, move], [0, 0, 0, 1]] + # + # Skip over the inverse transformation + # It is easier to just use inverse of trans in Matlab + # + fid.seek(12*4,1) + elif tag.type == FIFF.FIFFT_CH_INFO_STRUCT: + tag.data = Bunch() + tag.data['scanno'] = np.fromfile(fid, dtype=">i4", count=1) + tag.data['logno'] = np.fromfile(fid, dtype=">i4", count=1) + tag.data['kind'] = np.fromfile(fid, dtype=">i4", count=1) + tag.data['range'] = np.fromfile(fid, dtype=">i4", count=1) + tag.data['cal'] = np.fromfile(fid, dtype=">i4", count=1) + tag.data['coil_type'] = np.fromfile(fid, dtype=">i4", count=1) + # + # Read the coil coordinate system definition + # + tag.data['loc'] = np.fromfile(fid, dtype=">f4", count=12) + tag.data['coil_trans'] = None + tag.data['eeg_loc'] = None + tag.data['coord_frame'] = FIFF.FIFFV_COORD_UNKNOWN + # + # Convert loc into a more useful format + # + loc = tag.data.loc + kind = tag.data.kind + if kind == FIFF.FIFFV_MEG_CH or kind == FIFF.FIFFV_REF_MEG_CH: + tag.data.coil_trans = np.r_[ np.c_[loc[3:5], loc[6:8], + loc[9:11], loc[0:2] ], + [0, 0, 0, 1 ] ] + tag.data.coord_frame = FIFF.FIFFV_COORD_DEVICE + elif tag.data.kind == FIFF.FIFFV_EEG_CH: + if np.norm(loc[3:5]) > 0: + tag.data.eeg_loc = np.c_[ loc[0:2], loc[3:5] ] + else: + tag.data.eeg_loc = loc[1:3] + tag.data.coord_frame = FIFF.FIFFV_COORD_HEAD + # + # Unit and exponent + # + tag.data['unit'] = np.fromfile(fid, dtype=">i4", count=1) + tag.data['unit_mul'] = np.fromfile(fid, dtype=">i4", count=1) + # + # Handle the channel name + # + ch_name = np.fromfile(fid, dtype=">c", count=16) + # + # Omit nulls + # + length = 16 + for k in range(16): + if ch_name(k) == 0: + length = k-1 + break + tag.data['ch_name'] = ch_name[1:length] + import pdb; pdb.set_trace() + + elif tag.type == FIFF.FIFFT_OLD_PACK: + offset = np.fromfile(fid, dtype=">f4", count=1) + scale = np.fromfile(fid, dtype=">f4", count=1) + tag.data = np.fromfile(fid, dtype=">h2", count=(tag.size-8)/2) + tag.data = scale*tag.data + offset + elif tag.type == FIFF.FIFFT_DIR_ENTRY_STRUCT: + tag.data = list() + for _ in range(tag.size/16-1): + s = fid.read(4*4) + tag.data.append(Tag(*struct.unpack(">iIii", s))) + else: + raise ValueError, 'Unimplemented tag data type %s' % tag.type + + if tag.next != FIFF.FIFFV_NEXT_SEQ: + # f.seek(tag.next,0) + fid.seek(tag.next, 1) # XXX : fix? pb when tag.next < 0 + + return tag diff --git a/fiff/tree.py b/fiff/tree.py new file mode 100644 index 0000000..9919d4c --- /dev/null +++ b/fiff/tree.py @@ -0,0 +1,85 @@ +from .bunch import Bunch +from .read_tag import read_tag + +def make_dir_tree(fid, directory, start=0, indent=0): + """Create the directory tree structure + """ + FIFF_BLOCK_START = 104 + FIFF_BLOCK_END = 105 + FIFF_FILE_ID = 100 + FIFF_BLOCK_ID = 103 + FIFF_PARENT_BLOCK_ID = 110 + + verbose = 0 + + if directory[start].kind == FIFF_BLOCK_START: + tag = read_tag(fid, directory[start].pos) + block = tag.data + else: + block = 0 + + if verbose: + for k in range(indent): + print '\t' + print 'start { %d\n' % block + + nchild = 0 + this = start + + tree = Bunch() + tree['block'] = block + tree['id'] = None + tree['parent_id'] = None + tree['nent'] = 0 + tree['nchild'] = 0 + tree['directory'] = directory[this] + tree['children'] = Bunch(block=None, id=None, parent_id=None, nent=None, + nchild=None, directory=None, children=None) + + while this < len(directory): + if directory[this].kind == FIFF_BLOCK_START: + if this != start: + child, this = make_dir_tree(fid, directory, this, indent+1) + tree.nchild = tree.nchild + 1 + tree.children[tree.nchild] = child + elif directory[this].kind == FIFF_BLOCK_END: + tag = read_tag(fid, directory[start].pos) + if tag.data == block: + break + else: + tree.nent = tree.nent + 1 + if tree.nent == 1: + tree.directory = list() + tree.directory.append(directory[this]) + # + # Add the id information if available + # + if block == 0: + if directory[this].kind == FIFF_FILE_ID: + tag = read_tag(fid, directory[this].pos) + tree.id = tag.data + else: + if directory[this].kind == FIFF_BLOCK_ID: + tag = read_tag(fid, directory[this].pos) + tree.id = tag.data + elif directory[this].kind == FIFF_PARENT_BLOCK_ID: + tag = read_tag(fid, directory[this].pos) + tree.parent_id = tag.data + this = this + 1 + # + # Eliminate the empty directory + # + if tree.nent == 0: + tree.directory = [] + + if verbose: + for k in range(indent+1): + print '\t' + print 'block = %d nent = %d nchild = %d\n' % (tree.block, tree.nent, + tree.nchild) + for k in range(indent): + print '\t' + print 'end } %d\n' % block + + last = this + return tree, last diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..e69de29 -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/python-mne.git _______________________________________________ debian-med-commit mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit
