def test_empty(self): dummy = SpikeData() assert len(dummy.cfg) == 0 assert dummy.dimord is None for attr in [ "channel", "data", "sampleinfo", "samplerate", "trialid", "trialinfo", "unit" ]: assert getattr(dummy, attr) is None with pytest.raises(SPYTypeError): SpikeData({})
def test_nparray(self): dummy = SpikeData(self.data) assert dummy.dimord == ["sample", "channel", "unit"] assert dummy.channel.size == self.num_chn # NOTE: SpikeData.sample is currently empty # assert dummy.sample.size == self.num_smp assert dummy.unit.size == self.num_unt assert (dummy.sampleinfo == [0, self.data[:, 0].max()]).min() assert dummy.trialinfo.shape == (1, 0) assert np.array_equal(dummy.data, self.data) # wrong shape for data-type with pytest.raises(SPYValueError): SpikeData(np.ones((3, )))
def test_trialretrieval(self): # test ``_get_trial`` with NumPy array: regular order dummy = SpikeData(self.data, trialdefinition=self.trl) smp = self.data[:, 0] for trlno, start in enumerate(range(0, self.ns, 5)): idx = np.intersect1d( np.where(smp >= start)[0], np.where(smp < start + 5)[0]) trl_ref = self.data[idx, ...] assert np.array_equal(dummy._get_trial(trlno), trl_ref) # test ``_get_trial`` with NumPy array: swapped dimensions dummy = SpikeData(self.data2, trialdefinition=self.trl, dimord=["unit", "channel", "sample"]) smp = self.data2[:, -1] for trlno, start in enumerate(range(0, self.ns, 5)): idx = np.intersect1d( np.where(smp >= start)[0], np.where(smp < start + 5)[0]) trl_ref = self.data2[idx, ...] assert np.array_equal(dummy._get_trial(trlno), trl_ref)
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_saveload(self): with tempfile.TemporaryDirectory() as tdir: fname = os.path.join(tdir, "dummy") # basic but most important: ensure object integrity is preserved checkAttr = [ "channel", "data", "dimord", "sampleinfo", "samplerate", "trialinfo", "unit" ] dummy = SpikeData(self.data, samplerate=10) dummy.save(fname) filename = construct_spy_filename(fname, dummy) # dummy2 = SpikeData(filename) # for attr in checkAttr: # assert np.array_equal(getattr(dummy, attr), getattr(dummy2, attr)) dummy3 = load(fname) for attr in checkAttr: assert np.array_equal(getattr(dummy3, attr), getattr(dummy, attr)) save(dummy3, container=os.path.join(tdir, "ymmud")) dummy4 = load(os.path.join(tdir, "ymmud")) for attr in checkAttr: assert np.array_equal(getattr(dummy4, attr), getattr(dummy, attr)) del dummy3, dummy4 # avoid PermissionError in Windows time.sleep(0.1) # wait to kick-off garbage collection # overwrite existing container w/new data dummy.samplerate = 20 dummy.save() dummy2 = load(filename=filename) assert dummy2.samplerate == 20 del dummy, dummy2 time.sleep(0.1) # wait to kick-off garbage collection # ensure trialdefinition is saved and loaded correctly dummy = SpikeData(self.data, trialdefinition=self.trl, samplerate=10) dummy.save(fname, overwrite=True) dummy2 = load(filename) assert np.array_equal(dummy.sampleinfo, dummy2.sampleinfo) assert np.array_equal(dummy._t0, dummy2._t0) assert np.array_equal(dummy.trialinfo, dummy2.trialinfo) del dummy, dummy2 time.sleep(0.1) # wait to kick-off garbage collection # swap dimensions and ensure `dimord` is preserved dummy = SpikeData(self.data, dimord=["unit", "channel", "sample"], samplerate=10) dummy.save(fname + "_dimswap") filename = construct_spy_filename(fname + "_dimswap", dummy) dummy2 = load(filename) assert dummy2.dimord == dummy.dimord assert dummy2.unit.size == self.num_smp # swapped assert dummy2.data.shape == dummy.data.shape # Delete all open references to file objects b4 closing tmp dir del dummy, dummy2 time.sleep(0.1)