Ejemplo n.º 1
0
    def _get_head(self):
        """Wraps EEGFile._get_head to modify the channel information"""
        # Retreive data
        head = super(MontageFile, self)._get_head()
        chan = head.chan

        # Check montage labels
        labels = [c.label for c in chan]
        labels_lower = [l.lower() for l in labels]
        new_chan = []
        self.indices = []
        for label in self.montage:
            # Montage could use different case from file
            elec1, elec2 = label.lower().split('-')
            elec1 = labels[labels_lower.index(elec1)]
            elec2 = labels[labels_lower.index(elec2)]
            # Create chan dict for new chan
            cnew = chan[labels.index(elec1)]
            label = elec1 + '-' + elec2
            new_chan.append(cnew._replace(label=label))
            # These are used in _get_blocks
            self.indices.append((label, elec1, elec2))

        #
        descr = [(c.label, 'i2', c.nsblock) for c in new_chan]
        self._block_descriptor = BlockDescriptor(descr)
        return head._replace(chan=new_chan, nchan=len(new_chan))
Ejemplo n.º 2
0
    def __init__(self, tstart, tend, samples, labels=None, name='samples'):
        """Create a SampleFile interface to the data in samples

        tstart  : start time of file
        tend    : end time of file
        samples : list of arrays of samples
        labels  : names of channels
        """
        # Establish the number of channels
        nchan = len(samples)

        # Invent labels if necessary
        if labels is None:
            labels = ['Chan {0}'.format(n) for n in range(1, nchan + 1)]

        # Enforce equal sample rates
        nsamples = len(samples[0])
        if not all((len(x) == nsamples) for x in samples):
            raise EEGUnequalSamplesError("samples must be of equal length")

        # Check number of labels
        if len(labels) != nchan:
            msg = "Expected {0} labels found {1}"
            raise ValueError(msg.format(nchan, len(labels)))

        # Determine block size
        samplenos = [len(x) for x in samples]
        secsdur = self.as_seconds(tend, tstart)
        nblocks = _optimal_nblocks(secsdur, samplenos)

        # Determine the number of seconds in a block as an integer
        secsblock = secsdur / nblocks
        if secsblock == int(secsblock):
            secsblock = int(secsblock)

        # Create channel header structures
        chan = []
        kwargs = {'calib':1, 'offset':0, 'dim':'uV'}
        for lab, sam in zip(labels, samples):
            nsblock = len(sam) // nblocks
            chan.append(Chan(label=lab, nsblock=nsblock, **kwargs))

        # Create main header structure
        head = Head(tstart=tstart, secsblock=secsblock, chan=chan,
                    nchan=len(chan), nblocks=nblocks)

        # Store what's needed for later
        self.__samples = samples
        self._head = head
        self.name = name

        # Used in _get_blocks
        descr = [(c.label, 'i2', c.nsblock) for c in chan]
        self._block_descriptor = BlockDescriptor(descr)

        # Initialise
        super(SampleFile, self).__init__(self)
Ejemplo n.º 3
0
    def _read_head(self):
        """Read the main file header"""
        # Actually read the file:
        self._seek(0)
        wg1_head = self._fromfile(_head_descr)[0]

        # Extract channels
        nchan = int(wg1_head["nchan"])
        raw_chan = wg1_head["wg1_chan"][:nchan]

        def as_chan(c):
            return Chan(
                label=c["label"].strip(), dim="uV", calib=1e-3 * c["calib"], offset=0, nsblock=_wg1_nsblock, finfo=c
            )

        head = Head(
            pat_id="",
            rec_id=split(self.name)[1],
            tstart=self._wg1_datetime(wg1_head["wg1_daynum"], wg1_head["wg1_msnum"]),
            nblocks=-1,
            secsblock=_wg1_nsblock * 1e-6 * int(wg1_head["wg1_dtusec"]),
            nchan=int(wg1_head["nchan"]),
            chan=[as_chan(c) for c in raw_chan],
            fmt="wg1",
            finfo=wg1_head,
        )

        # How the block will be represented in memory
        descr = [(c.label, "i2", c.nsblock) for c in head.chan]
        self._block_descr = BlockDescriptor(descr)

        # How the block appears on disk
        self._headlen = _wg1_headlen
        nchan = head.nchan
        ntotal, nbegin = wg1_head["wg1_ntotal"], wg1_head["wg1_nbegin"]
        self._blocklen = ntotal * _wg1_nsblock
        pad1 = _wg1_nsblock * nbegin - 4 * nchan
        pad2 = _wg1_nsblock * (ntotal - nbegin - nchan)
        pad1 = pad1 or ""
        pad2 = pad2 or ""
        self._block_descr_raw = HeadDescriptor(
            [
                ("chan", HeadDescriptor([("offset", "i2"), ("pad", "u2")]), nchan),
                ("pad1", "S" + str(pad1)),
                ("bytes", str(_wg1_nsblock) + "u1", nchan),
                ("pad2", "S" + str(pad2)),
            ],
            nbytes=ntotal * _wg1_nsblock,
        )

        return head
Ejemplo n.º 4
0
class ChanMapFile(EEGFile):
    """ChanMapFile class
    """

    def __init__(self, infile, chanmap=None):
        """Store the chanmap and initialise"""
        self._chanmap = chanmap
        super(ChanMapFile, self).__init__(infile)

    def _setup_chanmap(self, channames, chanmap):
        """Returns a new chanmap based on the source chan info"""
        # If not provided fill the identity map here
        if chanmap is None:
            chanmap = zip(channames, channames)
        return chanmap

    def _get_head(self):
        """Override EEGFile._get_head to modify channels"""
        # Read original header
        head = super(ChanMapFile, self)._get_head()
        chan = head.chan

        # Finalise the chanmap based on the source channel list
        channames = [c.label for c in chan]
        self._chanmap = self._setup_chanmap(channames, self._chanmap)

        # Create new channel data
        chan_d = dict((c.label, c) for c in chan)
        new_chan = []
        for c_old, c_new in self._chanmap:
            new_chan.append(chan_d[c_old]._replace(label=c_new))

        # Prepare data blocks
        descr = [(c.label, 'i2', c.nsblock) for c in new_chan]
        self._block_descriptor = BlockDescriptor(descr)

        # Return head with modified information
        return head._replace(chan=new_chan, nchan=len(new_chan))

    def _get_blocks(self, n1, n2):
        """Override EEGFile._get_blocks to modify channels"""
        # Read original blocks
        old_blocks = super(ChanMapFile, self)._get_blocks(n1, n2)

        # Map into the new block
        new_blocks = self._block_descriptor.new(len(old_blocks))
        for c_old, c_new in self._chanmap:
            new_blocks[c_new] = old_blocks[c_old]

        return new_blocks
Ejemplo n.º 5
0
class MontageFile(EEGFile):
    def __init__(self, infile, montage, *args, **kwargs):
        """Set montage and initialise EEGFile object"""
        if not montage in MONTAGES:
            msg = "Unrecognised montage: '{0}'".format(montage)
            raise UnrecognisedMontageError(msg)
        self.montage = MONTAGES[montage]
        EEGFile.__init__(self, infile, *args, **kwargs)

    def _get_head(self):
        """Wraps EEGFile._get_head to modify the channel information"""
        # Retreive data
        head = super(MontageFile, self)._get_head()
        chan = head.chan

        # Check montage labels
        labels = [c.label for c in chan]
        labels_lower = [l.lower() for l in labels]
        new_chan = []
        self.indices = []
        for label in self.montage:
            # Montage could use different case from file
            elec1, elec2 = label.lower().split('-')
            elec1 = labels[labels_lower.index(elec1)]
            elec2 = labels[labels_lower.index(elec2)]
            # Create chan dict for new chan
            cnew = chan[labels.index(elec1)]
            label = elec1 + '-' + elec2
            new_chan.append(cnew._replace(label=label))
            # These are used in _get_blocks
            self.indices.append((label, elec1, elec2))

        #
        descr = [(c.label, 'i2', c.nsblock) for c in new_chan]
        self._block_descriptor = BlockDescriptor(descr)
        return head._replace(chan=new_chan, nchan=len(new_chan))

    def _get_blocks(self, n1, n2):
        """Wraps EEGFile._get_blocks to change the montage of the data"""
        block = EEGFile._get_blocks(self, n1, n2)
        new_block = self._block_descriptor.new(len(block))
        for label, elec1, elec2 in self.indices:
            new_block[label] = block[elec2] - block[elec1]
        return new_block
Ejemplo n.º 6
0
    def _get_head(self):
        """Override EEGFile._get_head to modify channels"""
        # Read original header
        head = super(ChanMapFile, self)._get_head()
        chan = head.chan

        # Finalise the chanmap based on the source channel list
        channames = [c.label for c in chan]
        self._chanmap = self._setup_chanmap(channames, self._chanmap)

        # Create new channel data
        chan_d = dict((c.label, c) for c in chan)
        new_chan = []
        for c_old, c_new in self._chanmap:
            new_chan.append(chan_d[c_old]._replace(label=c_new))

        # Prepare data blocks
        descr = [(c.label, 'i2', c.nsblock) for c in new_chan]
        self._block_descriptor = BlockDescriptor(descr)

        # Return head with modified information
        return head._replace(chan=new_chan, nchan=len(new_chan))
Ejemplo n.º 7
0
class Wg1File(IOFile):
    """Specialised for reading WG1 files"""

    # String for use when opening the file
    _binary = "b"

    def _read_head(self):
        """Read the main file header"""
        # Actually read the file:
        self._seek(0)
        wg1_head = self._fromfile(_head_descr)[0]

        # Extract channels
        nchan = int(wg1_head["nchan"])
        raw_chan = wg1_head["wg1_chan"][:nchan]

        def as_chan(c):
            return Chan(
                label=c["label"].strip(), dim="uV", calib=1e-3 * c["calib"], offset=0, nsblock=_wg1_nsblock, finfo=c
            )

        head = Head(
            pat_id="",
            rec_id=split(self.name)[1],
            tstart=self._wg1_datetime(wg1_head["wg1_daynum"], wg1_head["wg1_msnum"]),
            nblocks=-1,
            secsblock=_wg1_nsblock * 1e-6 * int(wg1_head["wg1_dtusec"]),
            nchan=int(wg1_head["nchan"]),
            chan=[as_chan(c) for c in raw_chan],
            fmt="wg1",
            finfo=wg1_head,
        )

        # How the block will be represented in memory
        descr = [(c.label, "i2", c.nsblock) for c in head.chan]
        self._block_descr = BlockDescriptor(descr)

        # How the block appears on disk
        self._headlen = _wg1_headlen
        nchan = head.nchan
        ntotal, nbegin = wg1_head["wg1_ntotal"], wg1_head["wg1_nbegin"]
        self._blocklen = ntotal * _wg1_nsblock
        pad1 = _wg1_nsblock * nbegin - 4 * nchan
        pad2 = _wg1_nsblock * (ntotal - nbegin - nchan)
        pad1 = pad1 or ""
        pad2 = pad2 or ""
        self._block_descr_raw = HeadDescriptor(
            [
                ("chan", HeadDescriptor([("offset", "i2"), ("pad", "u2")]), nchan),
                ("pad1", "S" + str(pad1)),
                ("bytes", str(_wg1_nsblock) + "u1", nchan),
                ("pad2", "S" + str(pad2)),
            ],
            nbytes=ntotal * _wg1_nsblock,
        )

        return head

    # ReadBlock reads in and converts one block of EEG data
    # at a time.
    def _read_block(self, n):
        """Read in one datablock"""
        # Read raw block
        self._seek(self._headlen + n * self._blocklen)
        block_raw = self._fromfile(self._block_descr_raw)

        # Check against magic end value:
        if block_raw["chan"]["pad"][0][0] == _wg1_end:
            self.nblocks = n
            raise EOFError

        # Convert to standard block type
        chan = self.get_chan()
        sigs = block_raw["bytes"][0]
        block = self._block_descr.new(1)
        for n, c in enumerate(chan):
            label = c.label
            index = c.finfo["wg1_index"]
            sig = sigs[n]
            offset = block_raw["chan"]["offset"][0, n]
            diff = _wg1_conv[sig].cumsum()
            block[label] = diff - offset
        # import pdb; pdb.set_trace()
        return block

    def _read_blocks(self, n1, n2):
        blocks = []
        for n in range(n1, n2):
            try:
                blocks.append(self._read_block(n))
            except EOFError:
                if not blocks:
                    raise
                else:
                    break
        return self._block_descr.concatenate(blocks)

    def _wg1_datetime(self, daynum, millisecond):
        """Convert two numbers in wg1 file to datetime"""
        day = daynum - 0x250000 - 15755 - 1
        timestamp = day * 86400 + millisecond / 1000.0
        return datetime.fromtimestamp(timestamp)