示例#1
0
    def testEventDataset(self):
        # baisc checks
        self.failUnlessRaises(DatasetError, EventDataset)

        # simple data
        samples = N.arange(240).reshape(10, 2, 3, 4)

        # copy constructor does not work on non-2D data
        self.failUnlessRaises(DatasetError, EventDataset, samples=samples)

        # try case without extra features
        evs = [Event(onset=2, duration=2, label=1, chunk=2),
               Event(onset=5, duration=1, label=2, chunk=2),
               Event(onset=7, duration=2, label=3, chunk=4)]

        ds = EventDataset(samples=samples, events=evs)
        self.failUnless(ds.nfeatures == 48)
        self.failUnless(ds.nsamples == 3)
        self.failUnless((ds.labels == [1,2,3]).all())
        self.failUnless((ds.chunks == [2,2,4]).all())
        mr = ds.mapReverse(N.arange(48))
        self.failUnless((mr == N.arange(48).reshape(2,2,3,4)).all())

        # try case with extra features
        evs = [Event(onset=2, duration=2, label=1, features=[2,3]),
               Event(onset=5, duration=2, label=1, features=[4,5]),
               Event(onset=7, duration=2, label=1, features=[6,7]),]
        ds = EventDataset(samples=samples, events=evs)
        # we have 2 additional features
        self.failUnless(ds.nfeatures == 50)
        self.failUnless(ds.nsamples == 3)
        self.failUnless((ds.labels == [1,1,1]).all())
        self.failUnless((ds.chunks == [0,1,2]).all())
        # now for the long awaited -- map back into two distinct
        # feature spaces
        mr = ds.mapReverse(N.arange(50))
        # we get two sets of feature spaces (samples and extra features)
        self.failUnless(len(mr) == 2)
        msamples, mxfeat = mr
        # the sample side should be identical to the case without extra features
        self.failUnless((msamples == N.arange(48).reshape(2,2,3,4)).all())
        # the extra features should be flat
        self.failUnless((mxfeat == (48,49)).all())

        # now take a look at 
        orig = ds.O
        self.failUnless(len(mr) == 2)
        osamples, oextra = orig
        self.failUnless((oextra == [[2,3],[4,5],[6,7]]).all())
        self.failUnless(osamples.shape == samples.shape)
        # check that all samples not covered by an event are zero
        filt = N.array([True,True,False,False,True,False,False,False,False,True])
        self.failUnless(N.sum(osamples[filt]) == 0)
        self.failUnless((osamples[N.negative(filt)] > 0).all())
示例#2
0
文件: nifti.py 项目: gorlins/PyMVPA
    def __init__(self, samples=None, events=None, mask=None, evconv=False,
                 storeoffset=False, tr=None, enforce_dim=4, **kwargs):
        """
        :Paramaters:
          mask: str | NiftiImage | ndarray
            Filename of a NIfTI image or a `NiftiImage` instance or an ndarray
            of appropriate shape.
          evconv: bool
            Convert event definitions using `onset` and `duration` in some
            temporal unit into #sample notation.
          storeoffset: Bool
            Whether to store temproal offset information when converting
            Events into descrete time. Only considered when evconv == True.
          tr: float
            Temporal distance of two adjacent NIfTI volumes. This can be used
            to override the corresponding value in the NIfTI header.
          enforce_dim : int or None
            If not None, it is the dimensionality of the data to be enforced,
            commonly 4D for the data, and 3D for the mask in case of fMRI.
        """
        # check if we are in copy constructor mode
        if events is None:
            EventDataset.__init__(self, samples=samples, events=events,
                                  mask=mask, **kwargs)
            return

        nifti = getNiftiFromAnySource(samples, ensure=True,
                                      enforce_dim=enforce_dim)
        # no copying
        samples = nifti.data

        # do not put the whole NiftiImage in the dict as this will most
        # likely be deepcopy'ed at some point and ensuring data integrity
        # of the complex Python-C-Swig hybrid might be a tricky task.
        # Only storing the header dict should achieve the same and is more
        # memory efficient and even simpler
        dsattr = {'niftihdr': nifti.header}

        # determine TR, take from NIfTI header by default
        dt = nifti.rtime
        # override if necessary
        if not tr is None:
            dt = tr

        # NiftiDataset uses a DescreteMetric with cartesian
        # distance and element size from the NIfTI header
        # 'voxdim' is (x,y,z) while 'samples' are (t,z,y,x)
        elementsize = [dt] + [i for i in reversed(nifti.voxdim)]
        # XXX metric might be inappropriate if boxcar has length 1
        # might move metric setup after baseclass init and check what has
        # really happened
        metric = DescreteMetric(elementsize=elementsize,
                                distance_function=cartesianDistance)

        # convert EVs if necessary -- not altering original
        if evconv:
            if dt == 0:
                raise ValueError, "'dt' cannot be zero when converting Events"

            events = [ev.asDescreteTime(dt, storeoffset) for ev in events]
        else:
            # do not touch the original
            events = deepcopy(events)

            # forcefully convert onset and duration into integers, as expected
            # by the baseclass
            for ev in events:
                oldonset = ev['onset']
                oldduration = ev['duration']
                ev['onset'] = int(ev['onset'])
                ev['duration'] = int(ev['duration'])
                if not oldonset == ev['onset'] \
                   or not oldduration == ev['duration']:
                    warning("Loosing information during automatic integer "
                            "conversion of EVs. Consider an explicit conversion"
                            " by setting `evconv` in ERNiftiDataset().")

        # pull mask array from NIfTI (if present)
        if mask is None:
            pass
        elif isinstance(mask, N.ndarray):
            # plain array can be passed on to base class
            pass
        else:
            mask_nim = getNiftiFromAnySource(mask)
            if not mask_nim is None:
                mask = getNiftiData(mask_nim)
            else:
                raise ValueError, "Cannot load mask from '%s'" % mask

        # finally init baseclass
        EventDataset.__init__(self, samples=samples, events=events,
                              mask=mask, dametric=metric, dsattr=dsattr,
                              **kwargs)