Esempio n. 1
0
    def test_dataselection(self):
        dummy = AnalogData(data=self.data,
                           trialdefinition=self.trl,
                           samplerate=self.samplerate)
        trialSelections = [
            "all",  # enforce below selections in all trials of `dummy`
            [3, 1]  # minimally unordered
        ]
        chanSelections = [
            ["channel03", "channel01", "channel01",
             "channel02"],  # string selection w/repetition + unordered
            [4, 2, 2, 5, 5],  # repetition + unorderd
            range(5, 8),  # narrow range
            slice(-2, None)  # negative-start slice
        ]
        toiSelections = [
            "all",  # non-type-conform string
            [0.6],  # single inexact match
            [-0.2, 0.6, 0.9, 1.1, 1.3, 1.6, 1.8, 2.2, 2.45,
             3.]  # unordered, inexact, repetions
        ]
        toilimSelections = [
            [0.5, 1.5],  # regular range
            [1.5, 2.0],  # minimal range (just two-time points)
            [1.0, np.inf]  # unbounded from above
        ]
        timeSelections = list(zip(["toi"] * len(toiSelections), toiSelections)) \
            + list(zip(["toilim"] * len(toilimSelections), toilimSelections))

        idx = [slice(None)] * len(dummy.dimord)
        timeIdx = dummy.dimord.index("time")
        chanIdx = dummy.dimord.index("channel")

        for trialSel in trialSelections:
            for chanSel in chanSelections:
                for timeSel in timeSelections:
                    kwdict = {}
                    kwdict["trials"] = trialSel
                    kwdict["channels"] = chanSel
                    kwdict[timeSel[0]] = timeSel[1]
                    cfg = StructDict(kwdict)
                    # data selection via class-method + `Selector` instance for indexing
                    selected = dummy.selectdata(**kwdict)
                    selector = Selector(dummy, kwdict)
                    idx[chanIdx] = selector.channel
                    for tk, trialno in enumerate(selector.trials):
                        idx[timeIdx] = selector.time[tk]
                        assert np.array_equal(
                            selected.trials[tk].squeeze(),
                            dummy.trials[trialno][idx[0], :][:,
                                                             idx[1]].squeeze())
                    cfg.data = dummy
                    cfg.out = AnalogData(dimord=AnalogData._defaultDimord)
                    # data selection via package function and `cfg`: ensure equality
                    selectdata(cfg)
                    assert np.array_equal(cfg.out.channel, selected.channel)
                    assert np.array_equal(cfg.out.data, selected.data)
Esempio n. 2
0
    def test_dataselection(self):
        dummy = EventData(data=self.data,
                          trialdefinition=self.trl,
                          samplerate=2.0)
        # selections are chosen so that result is not empty
        trialSelections = [
            "all",  # enforce below selections in all trials of `dummy`
            [3, 1]  # minimally unordered
        ]
        eventidSelections = [
            [0, 0, 1],  # preserve repetition, don't convert to slice
            range(0, 2),  # narrow range
            slice(-2, None)  # negative-start slice
        ]
        toiSelections = [
            "all",  # non-type-conform string
            [-0.2, 0.6, 0.9, 1.1, 1.3, 1.6, 1.8, 2.2, 2.45,
             3.]  # unordered, inexact, repetions
        ]
        toilimSelections = [
            [0.5, 3.5],  # regular range
            [0.0, np.inf]  # unbounded from above
        ]
        timeSelections = list(zip(["toi"] * len(toiSelections), toiSelections)) \
            + list(zip(["toilim"] * len(toilimSelections), toilimSelections))

        eventidIdx = dummy.dimord.index("eventid")

        for trialSel in trialSelections:
            for eventidSel in eventidSelections:
                for timeSel in timeSelections:
                    kwdict = {}
                    kwdict["trials"] = trialSel
                    kwdict["eventids"] = eventidSel
                    kwdict[timeSel[0]] = timeSel[1]
                    cfg = StructDict(kwdict)
                    # data selection via class-method + `Selector` instance for indexing
                    selected = dummy.selectdata(**kwdict)
                    selector = Selector(dummy, kwdict)
                    tk = 0
                    for trialno in selector.trials:
                        if selector.time[tk]:
                            assert np.array_equal(
                                dummy.trials[trialno][selector.time[tk], :],
                                selected.trials[tk])
                            tk += 1
                    assert np.array_equal(
                        selected.eventid, dummy.eventid[np.unique(
                            selected.data[:, eventidIdx]).astype(np.intp)])
                    cfg.data = dummy
                    cfg.out = EventData(dimord=EventData._defaultDimord)
                    # data selection via package function and `cfg`: ensure equality
                    selectdata(cfg)
                    assert np.array_equal(cfg.out.eventid, selected.eventid)
                    assert np.array_equal(cfg.out.data, selected.data)
Esempio n. 3
0
    def test_validcallstyles(self):
        
        # data positional
        fname, = group_objects(self.data)
        assert fname == self.data.filename
        
        # data as keyword
        fname, = group_objects(data=self.data)
        assert fname == self.data.filename
        
        # data in cfg
        cfg = StructDict()
        cfg.data = self.data
        fname, = group_objects(cfg)
        assert fname == self.data.filename
        
        # 1. data positional, 2. cfg positional
        cfg = StructDict()
        cfg.groupbychan = None
        fname, = group_objects(self.data, cfg)
        assert fname == self.data.filename

        # 1. cfg positional, 2. data positional
        fname, = group_objects(cfg, self.data)
        assert fname == self.data.filename
        
        # data positional, cfg as keyword
        fname, = group_objects(self.data, cfg=cfg)
        assert fname == self.data.filename
        
        # cfg positional, data as keyword
        fname, = group_objects(cfg, data=self.data)
        assert fname == self.data.filename
    
        # both keywords
        fname, = group_objects(cfg=cfg, data=self.data)
        assert fname == self.data.filename
Esempio n. 4
0
    def test_dataselection(self):
        dummy = SpikeData(data=self.data,
                          trialdefinition=self.trl,
                          samplerate=2.0)
        # selections are chosen so that result is not empty
        trialSelections = [
            "all",  # enforce below selections in all trials of `dummy`
            [3, 1]  # minimally unordered
        ]
        chanSelections = [
            ["channel03", "channel01", "channel01",
             "channel02"],  # string selection w/repetition + unordered
            [4, 2, 2, 5, 5],  # repetition + unorderd
            range(5, 8),  # narrow range
            slice(-5, None)  # negative-start slice
        ]
        toiSelections = [
            "all",  # non-type-conform string
            [-0.2, 0.6, 0.9, 1.1, 1.3, 1.6, 1.8, 2.2, 2.45,
             3.]  # unordered, inexact, repetions
        ]
        toilimSelections = [
            [0.5, 3.5],  # regular range
            [1.0, np.inf]  # unbounded from above
        ]
        unitSelections = [
            ["unit1", "unit1", "unit2", "unit3"],  # preserve repetition
            [0, 0, 2, 3],  # preserve repetition, don't convert to slice
            range(1, 4),  # narrow range
            slice(-2, None)  # negative-start slice
        ]
        timeSelections = list(zip(["toi"] * len(toiSelections), toiSelections)) \
            + list(zip(["toilim"] * len(toilimSelections), toilimSelections))

        chanIdx = dummy.dimord.index("channel")
        unitIdx = dummy.dimord.index("unit")
        chanArr = np.arange(dummy.channel.size)

        for trialSel in trialSelections:
            for chanSel in chanSelections:
                for unitSel in unitSelections:
                    for timeSel in timeSelections:
                        kwdict = {}
                        kwdict["trials"] = trialSel
                        kwdict["channels"] = chanSel
                        kwdict["units"] = unitSel
                        kwdict[timeSel[0]] = timeSel[1]
                        cfg = StructDict(kwdict)
                        # data selection via class-method + `Selector` instance for indexing
                        selected = dummy.selectdata(**kwdict)
                        selector = Selector(dummy, kwdict)
                        tk = 0
                        for trialno in selector.trials:
                            if selector.time[tk]:
                                assert np.array_equal(
                                    dummy.trials[trialno][
                                        selector.time[tk], :],
                                    selected.trials[tk])
                                tk += 1
                        assert set(selected.data[:, chanIdx]).issubset(
                            chanArr[selector.channel])
                        assert set(selected.channel) == set(
                            dummy.channel[selector.channel])
                        assert np.array_equal(
                            selected.unit,
                            dummy.unit[np.unique(selected.data[:, unitIdx])])
                        cfg.data = dummy
                        cfg.out = SpikeData(dimord=SpikeData._defaultDimord)
                        # data selection via package function and `cfg`: ensure equality
                        selectdata(cfg)
                        assert np.array_equal(cfg.out.channel,
                                              selected.channel)
                        assert np.array_equal(cfg.out.unit, selected.unit)
                        assert np.array_equal(cfg.out.data, selected.data)
Esempio n. 5
0
    def test_invalidcallstyles(self):
        
        # expected error messages
        errmsg1 = "expected Syncopy data object(s) provided either via " +\
                 "`cfg`/keyword or positional arguments, not both"
        errmsg2 = "expected Syncopy data object(s) provided either via `cfg` " +\
            "or as keyword argument, not both"
        errmsg3 = "expected either 'data' or 'dataset' in `cfg`/keywords, not both"
        
        # ensure things break reliably for 'data' as well as 'dataset'
        for key in ["data", "dataset"]:
        
            # data + cfg w/data
            cfg = StructDict()
            cfg[key] = self.data
            with pytest.raises(SPYValueError) as exc:
                group_objects(self.data, cfg)
            assert errmsg1 in str(exc.value)
            
            # data as positional + kwarg
            with pytest.raises(SPYValueError) as exc:
                group_objects(self.data, data=self.data)
            assert errmsg1 in str(exc.value)
            with pytest.raises(SPYValueError) as exc:
                group_objects(self.data, dataset=self.data)
            assert errmsg1 in str(exc.value)

            # cfg w/data + kwarg + positional
            with pytest.raises(SPYValueError) as exc:
                group_objects(self.data, cfg, data=self.data)
            assert errmsg1 in str(exc.value)
            with pytest.raises(SPYValueError) as exc:
                group_objects(self.data, cfg, dataset=self.data)
            assert errmsg1 in str(exc.value)
                
            # cfg w/data + kwarg
            with pytest.raises(SPYValueError) as exc:
                group_objects(cfg, data=self.data)
            assert errmsg2 in str(exc.value)
            with pytest.raises(SPYValueError) as exc:
                group_objects(cfg, dataset=self.data)
            assert errmsg2 in str(exc.value)

        # cfg (no data) but double-whammied
        cfg = StructDict()
        cfg.groupbychan = None
        with pytest.raises(SPYValueError)as exc:
            group_objects(self.data, cfg, cfg=cfg)
        assert "expected `cfg` either as positional or keyword argument, not both" in str(exc.value)
        
        # keyword set via cfg and kwarg
        with pytest.raises(SPYValueError) as exc:
            group_objects(self.data, cfg, groupbychan="invalid")
        assert "'non-default value for groupbychan'; expected no keyword arguments" in str(exc.value)
        
        # both data and dataset in cfg/keywords
        cfg = StructDict()
        cfg.data = self.data
        cfg.dataset = self.data
        with pytest.raises(SPYValueError)as exc:
            group_objects(cfg)
        assert errmsg3 in str(exc.value)
        with pytest.raises(SPYValueError)as exc:
            group_objects(data=self.data, dataset=self.data)
        assert errmsg3 in str(exc.value)

        # data/dataset do not contain Syncopy object
        with pytest.raises(SPYError)as exc:
            group_objects(data="invalid")
        assert "`data` must be Syncopy data object(s)!" in str(exc.value)
        
        # cfg is not dict/StructDict
        with pytest.raises(SPYTypeError)as exc:
            group_objects(cfg="invalid")
        assert "Wrong type of cfg: expected dictionary-like" in str(exc.value)

        # no data input whatsoever        
        with pytest.raises(SPYError)as exc:
            group_objects("invalid")
        assert "missing mandatory argument: `data`" in str(exc.value)
Esempio n. 6
0
    def test_varargin(self):
        
        # data positional
        allFnames = group_objects(*self.dataObjs)
        assert allFnames == [obj.filename for obj in self.dataObjs]

        # data in cfg
        cfg = StructDict()
        cfg.data = self.dataObjs
        fnameList = group_objects(cfg)
        assert allFnames == fnameList
        
        # group objects by single-letter "channels" in various ways
        for letter in ["L", "E", "I", "A"]:
            letterIdx = string.ascii_uppercase.index(letter)
            nOccurences = letterIdx + 1

            # data positional + keyword to get "reference"
            groupList = group_objects(*self.dataObjs, groupbychan=letter)
            assert len(groupList) == nOccurences
            
            # 1. data positional, 2. cfg positional
            cfg = StructDict()
            cfg.groupbychan = letter
            fnameList = group_objects(*self.dataObjs, cfg)
            assert groupList == fnameList

            # 1. cfg positional, 2. data positional
            fnameList = group_objects(cfg, *self.dataObjs)
            assert groupList == fnameList
            
            # data positional, cfg as keyword
            fnameList = group_objects(*self.dataObjs, cfg=cfg)
            assert groupList == fnameList
            
            # cfg w/data + keyword
            cfg = StructDict()
            cfg.dataset = self.dataObjs
            cfg.groupbychan = letter
            fnameList = group_objects(cfg)
            assert groupList == fnameList

            # data positional + select keyword
            fnameList = group_objects(*self.dataObjs[:letterIdx + 1], 
                                       select={"channels": [letter]})
            assert groupList == fnameList

            # data positional + cfg w/select
            cfg = StructDict()
            cfg.select = {"channels": [letter]}
            fnameList = group_objects(*self.dataObjs[:letterIdx + 1], cfg)
            assert groupList == fnameList

            # cfg w/data + select
            cfg = StructDict()
            cfg.data = self.dataObjs[:letterIdx + 1]
            cfg.select = {"channels": [letter]}
            fnameList = group_objects(cfg)
            assert groupList == fnameList
            
        # invalid selection
        with pytest.raises(SPYValueError) as exc:
            group_objects(*self.dataObjs, select={"channels": ["Z"]})
        assert "expected list/array of channel existing names or indices" in str(exc.value)

        # data does not only contain Syncopy objects        
        cfg = StructDict()
        cfg.data = self.dataObjs + ["invalid"]
        with pytest.raises(SPYError)as exc:
            group_objects(cfg)
        assert "`data` must be Syncopy data object(s)!" in str(exc.value)
Esempio n. 7
0
    def wrapper_cfg(*args, **kwargs):

        # First, parse positional arguments for dict-type inputs (`k` counts the
        # no. of dicts provided) and convert tuple of positional args to list
        cfg = None
        k = 0
        args = list(args)
        for argidx, arg in enumerate(args):
            if isinstance(arg, dict):
                cfgidx = argidx
                k += 1

        # If a dict was found, assume it's a `cfg` dict and extract it from
        # the positional argument list; if more than one dict was found, abort
        if k == 1:
            cfg = args.pop(cfgidx)
        elif k > 1:
            raise SPYValueError(
                legal="single `cfg` input",
                varname="cfg",
                actual="{0:d} `cfg` objects in input arguments".format(k))

        # Now parse provided keywords for `cfg` entry - if `cfg` was already
        # provided as positional argument, abort
        if kwargs.get("cfg") is not None:
            if cfg:
                lgl = "`cfg` either as positional or keyword argument, not both"
                raise SPYValueError(legal=lgl, varname="cfg")
            cfg = kwargs.pop("cfg")

        # If `cfg` was detected either in positional or keyword arguments, process it
        if cfg:

            # If `cfg` is not dict-like, abort (`StructDict` is a `dict` child)
            if not isinstance(cfg, dict):
                raise SPYTypeError(cfg,
                                   varname="cfg",
                                   expected="dictionary-like")

            # IMPORTANT: create a copy of `cfg` using `StructDict` constructor to
            # not manipulate `cfg` in user's namespace!
            cfg = StructDict(cfg)  # FIXME

            # If a method is called using `cfg`, non-default values for
            # keyword arguments must *only* to be provided via `cfg`
            defaults = get_defaults(func)
            for key, value in kwargs.items():
                if defaults.get(key, value) != value:
                    raise SPYValueError(
                        legal="no keyword arguments",
                        varname=key,
                        actual="non-default value for {}".format(key))

            # Translate any existing "yes" and "no" fields to `True` and `False`
            for key in cfg.keys():
                if str(cfg[key]) == "yes":
                    cfg[key] = True
                elif str(cfg[key]) == "no":
                    cfg[key] = False

        # No explicit `cfg`: rename `kwargs` to `cfg` to consolidate processing below;
        # IMPORTANT: this does *not* create a copy of `kwargs`, thus the `pop`-ing
        # below actually manipulates `kwargs` as well - crucial for the `kwargs.get("data")`
        # error checking!
        else:
            cfg = kwargs

        # If `cfg` contains keys 'data' or 'dataset' extract corresponding
        # entry and make it a positional argument (abort if both 'data'
        # and 'dataset' are present)
        data = cfg.pop("data", None)
        if cfg.get("dataset"):
            if data:
                lgl = "either 'data' or 'dataset' in `cfg`/keywords, not both"
                raise SPYValueError(legal=lgl, varname="cfg")
            data = cfg.pop("dataset")

        # If `cfg` did not contain `data`, look into `kwargs`
        if data is None:
            data = kwargs.pop("data", None)
            if kwargs.get("dataset"):
                if data:
                    lgl = "either `data` or `dataset` keyword, not both"
                    raise SPYValueError(legal=lgl, varname="data/dataset")
                data = kwargs.pop("dataset")

        # If Syncopy data object(s) were provided convert single objects to one-element
        # lists, ensure positional args do *not* contain add'l objects; ensure keyword
        # args (besides `cfg`) do *not* contain add'l objects; ensure `data` exclusively
        # contains Syncopy data objects. Finally, rename remaining positional arguments
        if data:
            if not isinstance(data, (tuple, list)):
                data = [data]
            if any([
                    isinstance(arg, spy.datatype.base_data.BaseData)
                    for arg in args
            ]):
                lgl = "Syncopy data object(s) provided either via `cfg`/keyword or " +\
                    "positional arguments, not both"
                raise SPYValueError(legal=lgl, varname="cfg/data")
            if kwargs.get("data") or kwargs.get("dataset"):
                lgl = "Syncopy data object(s) provided either via `cfg` or as " +\
                    "keyword argument, not both"
                raise SPYValueError(legal=lgl, varname="cfg.data")
            if any([
                    not isinstance(obj, spy.datatype.base_data.BaseData)
                    for obj in data
            ]):
                raise SPYError("`data` must be Syncopy data object(s)!")
            posargs = args

        # If `data` was not provided via `cfg` or as kw-arg, parse positional arguments
        if data is None:
            data = []
            posargs = []
            while args:
                arg = args.pop(0)
                if isinstance(arg, spy.datatype.base_data.BaseData):
                    data.append(arg)
                else:
                    posargs.append(arg)

        # Call function with unfolded `data` + modified positional/keyword args
        return func(*data, *posargs, **cfg)
Esempio n. 8
0
    def test_dataselection(self):
        dummy = SpectralData(
            data=self.data,
            trialdefinition=self.trl,
            samplerate=self.samplerate,
            taper=["TestTaper_0{}".format(k) for k in range(1, self.nt + 1)])
        trialSelections = [
            "all",  # enforce below selections in all trials of `dummy`
            [3, 1]  # minimally unordered
        ]
        chanSelections = [
            ["channel03", "channel01", "channel01",
             "channel02"],  # string selection w/repetition + unordered
            [4, 2, 2, 5, 5],  # repetition + unorderd
            range(5, 8),  # narrow range
            slice(-2, None)  # negative-start slice
        ]
        toiSelections = [
            "all",  # non-type-conform string
            [0.6],  # single inexact match
            [-0.2, 0.6, 0.9, 1.1, 1.3, 1.6, 1.8, 2.2, 2.45,
             3.]  # unordered, inexact, repetions
        ]
        toilimSelections = [
            [0.5, 1.5],  # regular range
            [1.5, 2.0],  # minimal range (just two-time points)
            [1.0, np.inf]  # unbounded from above
        ]
        foiSelections = [
            "all",  # non-type-conform string
            [2.6],  # single inexact match
            [1.1, 1.9, 2.1, 3.9, 9.2, 11.8, 12.9, 5.1,
             13.8]  # unordered, inexact, repetions
        ]
        foilimSelections = [
            [2, 11],  # regular range
            [1, 2.0],  # minimal range (just two-time points)
            [1.0, np.inf]  # unbounded from above
        ]
        taperSelections = [
            ["TestTaper_03", "TestTaper_01", "TestTaper_01",
             "TestTaper_02"],  # string selection w/repetition + unordered
            [0, 1, 1, 2, 3],  # preserve repetition, don't convert to slice
            range(2, 5),  # narrow range
            slice(0, 5, 2),  # slice w/non-unitary step-size
        ]
        timeSelections = list(zip(["toi"] * len(toiSelections), toiSelections)) \
            + list(zip(["toilim"] * len(toilimSelections), toilimSelections))
        freqSelections = list(zip(["foi"] * len(foiSelections), foiSelections)) \
            + list(zip(["foilim"] * len(foilimSelections), foilimSelections))

        idx = [slice(None)] * len(dummy.dimord)
        timeIdx = dummy.dimord.index("time")
        chanIdx = dummy.dimord.index("channel")
        freqIdx = dummy.dimord.index("freq")
        taperIdx = dummy.dimord.index("taper")

        for trialSel in trialSelections:
            for chanSel in chanSelections:
                for timeSel in timeSelections:
                    for freqSel in freqSelections:
                        for taperSel in taperSelections:
                            kwdict = {}
                            kwdict["trials"] = trialSel
                            kwdict["channels"] = chanSel
                            kwdict[timeSel[0]] = timeSel[1]
                            kwdict[freqSel[0]] = freqSel[1]
                            kwdict["tapers"] = taperSel
                            cfg = StructDict(kwdict)
                            # data selection via class-method + `Selector` instance for indexing
                            selected = dummy.selectdata(**kwdict)
                            selector = Selector(dummy, kwdict)
                            idx[chanIdx] = selector.channel
                            idx[freqIdx] = selector.freq
                            idx[taperIdx] = selector.taper
                            for tk, trialno in enumerate(selector.trials):
                                idx[timeIdx] = selector.time[tk]
                                indexed = dummy.trials[trialno][
                                    idx[0], ...][:, idx[1],
                                                 ...][:, :, idx[2], :][...,
                                                                       idx[3]]
                                assert np.array_equal(
                                    selected.trials[tk].squeeze(),
                                    indexed.squeeze())
                            cfg.data = dummy
                            cfg.out = SpectralData(
                                dimord=SpectralData._defaultDimord)
                            # data selection via package function and `cfg`: ensure equality
                            selectdata(cfg)
                            assert np.array_equal(cfg.out.channel,
                                                  selected.channel)
                            assert np.array_equal(cfg.out.freq, selected.freq)
                            assert np.array_equal(cfg.out.taper,
                                                  selected.taper)
                            assert np.array_equal(cfg.out.data, selected.data)