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)
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)
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)
def test_spectral_foifoilim(self): # this selection only works w/the dummy frequency data constructed above!!! selDict = { "foi": ( None, # trivial "selection" of entire contents, "all", # trivial "selection" of entire contents [1], # single entry lists [2.6], # inexact match [2, 9], # two disjoint frequencies [7.2, 8.3], # inexact from above [6.8, 11.9], # inexact from below [0.4, 13.1], # inexact from below, inexact from above [1.2, 2.9], # inexact from above, inexact from below [1.1, 1.9, 2.1, 3.9, 9.2, 11.8, 12.9, 5.1, 13.8], # alternating madness [2, 1, 11], # unsorted list [5, 2, 2, 3], # repetition [1, 1, 2, 3], # preserve repetition, don't convert to slice [2, 3, 4]), # sorted list (should be converted to slice-selection) "foilim": ( None, # trivial "selection" of entire contents, "all", # trivial "selection" of entire contents [2, 11], # regular range [1, 2], # minimal range (just two-time points) [1.0, np.inf], # unbounded from above [-np.inf, 12]) } # unbounded from below spc = SpectralData(data=self.data['SpectralData'], trialdefinition=self.trl['SpectralData'], samplerate=self.samplerate) allFreqs = spc.freq spcIdx = [slice(None)] * len(spc.dimord) freqIdx = spc.dimord.index("freq") for fselect in ["foi", "foilim"]: for freqSel in selDict[fselect]: sel = Selector(spc, {fselect: freqSel}).freq if freqSel is None or freqSel == "all": idx = slice(None) else: if fselect == "foi": idx = [] for fq in freqSel: idx.append(np.abs(allFreqs - fq).argmin()) else: idx = np.intersect1d( np.where(allFreqs >= freqSel[0])[0], np.where(allFreqs <= freqSel[1])[0]) # check that correct data was selected (all trials identical, just take 1st one) assert np.array_equal(spc.freq[idx], spc.freq[sel]) if not isinstance(idx, slice) and len(idx) > 1: freqSteps = np.diff(idx) if freqSteps.min() == freqSteps.max() == 1: idx = slice(idx[0], idx[-1] + 1, 1) # check correct format of selector (list -> slice etc.) assert np.array_equal(idx, sel) # perform actual data-selection and ensure identity of results selected = selectdata(spc, {fselect: freqSel}) spcIdx[freqIdx] = idx assert np.array_equal(selected.freq, spc.freq[sel]) for trialno in range(len(spc.trials)): assert np.array_equal(selected.trials[trialno], spc.trials[trialno][tuple(spcIdx)])
def test_discrete_toitoilim(self): # this only works w/the equidistant trials constructed above!!! selDict = { "toi": ( None, # trivial "selection" of entire contents "all", # trivial "selection" of entire contents [0.5], # single entry lists [0.6], # inexact match [1.0, 2.5], # two disjoint time-points [1.2, 2.7], # inexact from above [1.9, 2.4], # inexact from below [0.4, 2.1], # inexact from below, inexact from above [1.6, 1.9], # inexact from above, inexact from below [-0.2, 0.6, 0.9, 1.1, 1.3, 1.6, 1.8, 2.2, 2.45, 3.], # alternating madness [2.0, 0.5, 2.5], # unsorted list [1.0, 0.5, 0.5, 1.5], # repetition [0.5, 0.5, 1.0, 1.5], # preserve repetition, don't convert to slice [0.5, 1.0, 1.5]), # sorted list (should be converted to slice-selection) "toilim": ( None, # trivial "selection" of entire contents "all", # trivial "selection" of entire contents [0.5, 1.5], # regular range [1.5, 2.0], # minimal range (just two-time points) [1.0, np.inf], # unbounded from above [-np.inf, 1.0]) } # unbounded from below # all trials have same time-scale for both `EventData` and `SpikeData`: take 1st one as reference trlTime = list((np.arange( 0, self.trl["SpikeData"][0, 1] - self.trl["SpikeData"][0, 0]) + self.trl["SpikeData"][0, 2]) / 2) # the below method of extracting spikes satisfying `toi`/`toilim` only works w/equidistant trials! for dclass in ["SpikeData", "EventData"]: discrete = getattr(spd, dclass)(data=self.data[dclass], trialdefinition=self.trl[dclass], samplerate=self.samplerate) for tselect in ["toi", "toilim"]: for timeSel in selDict[tselect]: if isinstance(timeSel, list): smpIdx = [] for tp in timeSel: if np.isfinite(tp): smpIdx.append( np.abs(np.array(trlTime) - tp).argmin()) else: smpIdx.append(tp) result = [] sel = Selector(discrete, {tselect: timeSel}).time selected = selectdata(discrete, {tselect: timeSel}) tk = 0 for trlno in range(len(discrete.trials)): thisTrial = discrete.trials[trlno][:, 0] if isinstance(timeSel, list): if tselect == "toi": trlRes = [] for idx in smpIdx: trlRes += list( np.where(thisTrial == idx + trlno * self.lenTrial)[0]) else: start = smpIdx[0] + trlno * self.lenTrial stop = smpIdx[1] + trlno * self.lenTrial candidates = np.intersect1d( thisTrial[thisTrial >= start], thisTrial[thisTrial <= stop]) trlRes = [] for cand in candidates: trlRes += list( np.where(thisTrial == cand)[0]) else: trlRes = slice(0, thisTrial.size, 1) # ensure that actually selected data is correct assert np.array_equal( discrete.trials[trlno][trlRes, :], discrete.trials[trlno][sel[trlno], :]) if sel[trlno]: assert np.array_equal( selected.trials[tk], discrete.trials[trlno][sel[trlno], :]) tk += 1 if not isinstance(trlRes, slice) and len(trlRes) > 1: sampSteps = np.diff(trlRes) if sampSteps.min() == sampSteps.max() == 1: trlRes = slice(trlRes[0], trlRes[-1] + 1, 1) result.append(trlRes) # check correct format of selector (list -> slice etc.) assert result == sel
def test_continuous_toitoilim(self): # this only works w/the equidistant trials constructed above!!! selDict = { "toi": ( None, # trivial "selection" of entire contents "all", # trivial "selection" of entire contents [0.5], # single entry lists [0.6], # inexact match [1.0, 2.5], # two disjoint time-points [1.2, 2.7], # inexact from above [1.9, 2.4], # inexact from below [0.4, 2.1], # inexact from below, inexact from above [1.6, 1.9], # inexact from above, inexact from below [-0.2, 0.6, 0.9, 1.1, 1.3, 1.6, 1.8, 2.2, 2.45, 3.], # alternating madness [2.0, 0.5, 2.5], # unsorted list [1.0, 0.5, 0.5, 1.5], # repetition [0.5, 0.5, 1.0, 1.5], # preserve repetition, don't convert to slice [0.5, 1.0, 1.5]), # sorted list (should be converted to slice-selection) "toilim": ( None, # trivial "selection" of entire contents "all", # trivial "selection" of entire contents [0.5, 1.5], # regular range [1.5, 2.0], # minimal range (just two-time points) [1.0, np.inf], # unbounded from above [-np.inf, 1.0]) } # unbounded from below # all trials have same time-scale: take 1st one as reference trlTime = (np.arange( 0, self.trl["AnalogData"][0, 1] - self.trl["AnalogData"][0, 0]) + self.trl["AnalogData"][0, 2]) / self.samplerate ang = AnalogData(data=self.data["AnalogData"], trialdefinition=self.trl["AnalogData"], samplerate=self.samplerate) angIdx = [slice(None)] * len(ang.dimord) timeIdx = ang.dimord.index("time") # the below check only works for equidistant trials! for tselect in ["toi", "toilim"]: for timeSel in selDict[tselect]: sel = Selector(ang, {tselect: timeSel}).time if timeSel is None or timeSel == "all": idx = slice(None) else: if tselect == "toi": idx = [] for tp in timeSel: idx.append(np.abs(trlTime - tp).argmin()) else: idx = np.intersect1d( np.where(trlTime >= timeSel[0])[0], np.where(trlTime <= timeSel[1])[0]) # check that correct data was selected (all trials identical, just take 1st one) assert np.array_equal(ang.trials[0][idx, :], ang.trials[0][sel[0], :]) if not isinstance(idx, slice) and len(idx) > 1: timeSteps = np.diff(idx) if timeSteps.min() == timeSteps.max() == 1: idx = slice(idx[0], idx[-1] + 1, 1) result = [idx] * len(ang.trials) # check correct format of selector (list -> slice etc.) assert np.array_equal(result, sel) # perform actual data-selection and ensure identity of results selected = selectdata(ang, {tselect: timeSel}) for trialno in range(len(ang.trials)): angIdx[timeIdx] = result[trialno] assert np.array_equal(selected.trials[trialno], ang.trials[trialno][tuple(angIdx)])
def test_general(self): # construct expected results for `DiscreteData` objects defined above mapDict = {"unit": "SpikeData", "eventid": "EventData"} for prop, dclass in mapDict.items(): discrete = getattr(spd, dclass)(data=self.data[dclass], trialdefinition=self.trl[dclass], samplerate=self.samplerate) propIdx = discrete.dimord.index(prop) # convert selection from `selectDict` to a usable integer-list allResults = [] for selection in self.selectDict[prop]["valid"]: if isinstance(selection, slice): if selection.start is selection.stop is None: selects = [None] else: selects = list(range(getattr(discrete, prop).size))[selection] elif isinstance(selection, range): selects = list(selection) elif isinstance(selection, str) or selection is None: selects = [None] else: # selection is list/ndarray if isinstance(selection[0], str): avail = getattr(discrete, prop) else: avail = np.arange(getattr(discrete, prop).size) selects = [] for sel in selection: selects += list(np.where(avail == sel)[0]) # alternate (expensive) way to get by-trial selection indices result = [] for trial in discrete.trials: if selects[0] is None: res = slice(0, trial.shape[0], 1) else: res = [] for sel in selects: res += list(np.where(trial[:, propIdx] == sel)[0]) if len(res) > 1: steps = np.diff(res) if steps.min() == steps.max() == 1: res = slice(res[0], res[-1] + 1, 1) result.append(res) allResults.append(result) self.selectDict[prop]["result"] = tuple(allResults) # wrong type of data and/or selector with pytest.raises(SPYTypeError): Selector(np.empty((3, )), {}) with pytest.raises(SPYValueError): Selector(spd.AnalogData(), {}) ang = AnalogData(data=self.data["AnalogData"], trialdefinition=self.trl["AnalogData"], samplerate=self.samplerate) with pytest.raises(SPYTypeError): Selector(ang, ()) with pytest.raises(SPYValueError): Selector(ang, {"wrongkey": [1]}) # go through all data-classes defined above for dclass in self.classes: dummy = getattr(spd, dclass)(data=self.data[dclass], trialdefinition=self.trl[dclass], samplerate=self.samplerate) # test trial selection selection = Selector(dummy, {"trials": [3, 1]}) assert selection.trials == [3, 1] selected = selectdata(dummy, trials=[3, 1]) assert np.array_equal(selected.trials[0], dummy.trials[3]) assert np.array_equal(selected.trials[1], dummy.trials[1]) assert selected.trialdefinition.shape == (2, 4) assert np.array_equal(selected.trialdefinition[:, -1], dummy.trialdefinition[[3, 1], -1]) for trlSec in [None, "all"]: selection = Selector(dummy, {"trials": trlSec}) assert selection.trials == list(range(len(dummy.trials))) selected = selectdata(dummy, trials=trlSec) for tk, trl in enumerate(selected.trials): assert np.array_equal(trl, dummy.trials[tk]) assert np.array_equal(selected.trialdefinition, dummy.trialdefinition) with pytest.raises(SPYValueError): Selector(dummy, {"trials": [-1, 9]}) # test "simple" property setters handled by `_selection_setter` # for prop in ["eventid"]: for prop in ["channel", "taper", "unit", "eventid"]: if hasattr(dummy, prop): expected = self.selectDict[prop]["result"] for sk, sel in enumerate(self.selectDict[prop]["valid"]): solution = expected[sk] if dclass == "SpikeData" and prop == "channel": if isinstance(solution, slice): start, stop, step = solution.start, solution.stop, solution.step if start is None: start = 0 elif start < 0: start = len(dummy.channel) + start if stop is None: stop = len(dummy.channel) elif stop < 0: stop = len(dummy.channel) + stop if step not in [None, 1]: solution = list(range(start, stop))[solution] else: solution = slice(start, stop, step) # once we're sure `Selector` works, actually select data selection = Selector(dummy, {prop + "s": sel}) assert getattr(selection, prop) == solution selected = selectdata(dummy, {prop + "s": sel}) # process `unit` and `enventid` if prop in selection._byTrialProps: propIdx = selected.dimord.index(prop) propArr = np.unique( selected.data[:, propIdx]).astype(np.intp) assert set(getattr(selected, prop)) == set( getattr(dummy, prop)[propArr]) tk = 0 for trialno in range(len(dummy.trials)): if solution[ trialno]: # do not try to compare empty selections assert np.array_equal( selected.trials[tk], dummy.trials[trialno][ solution[trialno], :]) tk += 1 # `channel` is a special case for `SpikeData` objects elif dclass == "SpikeData" and prop == "channel": chanIdx = selected.dimord.index("channel") chanArr = np.arange(dummy.channel.size) assert set(selected.data[:, chanIdx]).issubset( chanArr[solution]) assert set(selected.channel) == set( dummy.channel[solution]) # everything else (that is not a `DiscreteData` child) else: idx = [slice(None)] * len(dummy.dimord) idx[dummy.dimord.index(prop)] = solution assert np.array_equal( np.array(dummy.data)[tuple(idx)], selected.data) assert np.array_equal( getattr(selected, prop), getattr(dummy, prop)[solution]) # ensure invalid selection trigger expected errors for ik, isel in enumerate( self.selectDict[prop]["invalid"]): with pytest.raises( self.selectDict[prop]["errors"][ik]): Selector(dummy, {prop + "s": isel}) else: # ensure objects that don't have a `prop` attribute complain with pytest.raises(SPYValueError): Selector(dummy, {prop + "s": [0]}) # ensure invalid `toi` + `toilim` specifications trigger expected errors if hasattr(dummy, "time") or hasattr(dummy, "trialtime"): for selection in ["toi", "toilim"]: for ik, isel in enumerate( self.selectDict[selection]["invalid"]): with pytest.raises( self.selectDict[selection]["errors"][ik]): Selector(dummy, {selection: isel}) # provide both `toi` and `toilim` with pytest.raises(SPYValueError): Selector(dummy, {"toi": [0], "toilim": [0, 1]}) else: # ensure objects that don't have `time` props complain properly with pytest.raises(SPYValueError): Selector(dummy, {"toi": [0]}) with pytest.raises(SPYValueError): Selector(dummy, {"toilim": [0]}) # ensure invalid `foi` + `foilim` specifications trigger expected errors if hasattr(dummy, "freq"): for selection in ["foi", "foilim"]: for ik, isel in enumerate( self.selectDict[selection]["invalid"]): with pytest.raises( self.selectDict[selection]["errors"][ik]): Selector(dummy, {selection: isel}) # provide both `foi` and `foilim` with pytest.raises(SPYValueError): Selector(dummy, {"foi": [0], "foilim": [0, 1]}) else: # ensure objects without `freq` property complain properly with pytest.raises(SPYValueError): Selector(dummy, {"foi": [0]}) with pytest.raises(SPYValueError): Selector(dummy, {"foilim": [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)