Beispiel #1
0
class NixIOReadTest(NixIOTest):

    filename = "testfile_readtest.h5"
    nixfile = None
    nix_blocks = None
    original_methods = dict()

    @classmethod
    def setUpClass(cls):
        if HAVE_NIX:
            cls.nixfile = cls.create_full_nix_file(cls.filename)

    def setUp(self):
        self.io = NixIO(self.filename, "ro")
        self.original_methods["_read_cascade"] = self.io._read_cascade
        self.original_methods["_update_maps"] = self.io._update_maps

    @classmethod
    def tearDownClass(cls):
        if HAVE_NIX:
            cls.nixfile.close()
            os.remove(cls.filename)

    def tearDown(self):
        self.io.close()

    def test_all_read(self):
        neo_blocks = self.io.read_all_blocks(lazy=False)
        nix_blocks = self.io.nix_file.blocks
        self.compare_blocks(neo_blocks, nix_blocks)
Beispiel #2
0
 def setUp(self):
     self.filename = "nixio_testfile_write.h5"
     self.writer = NixIO(self.filename, "ow")
     self.io = self.writer
     self.reader = nix.File.open(self.filename,
                                 nix.FileMode.ReadOnly,
                                 backend="h5py")
Beispiel #3
0
class NixIOReadTest(NixIOTest):
    nixfile = None
    nix_blocks = None

    @classmethod
    def setUpClass(cls):
        cls.tempdir = mkdtemp(prefix="nixiotest")
        cls.filename = os.path.join(cls.tempdir, "testnixio.nix")
        if HAVE_NIX:
            cls.nixfile = cls.create_full_nix_file(cls.filename)

    def setUp(self):
        self.io = NixIO(self.filename, "ro")

    @classmethod
    def tearDownClass(cls):
        if HAVE_NIX:
            cls.nixfile.close()
        shutil.rmtree(cls.tempdir)

    def tearDown(self):
        self.io.close()

    def test_all_read(self):
        neo_blocks = self.io.read_all_blocks()
        nix_blocks = self.io.nix_file.blocks
        self.compare_blocks(neo_blocks, nix_blocks)

    def test_iter_read(self):
        blocknames = [blk.name for blk in self.nixfile.blocks]
        for blk, nixname in zip(self.io.iter_blocks(), blocknames):
            self.assertEqual(blk.annotations["nix_name"], nixname)

    def test_nix_name_read(self):
        for nixblock in self.nixfile.blocks:
            nixname = nixblock.name
            neoblock = self.io.read_block(nixname=nixname)
            self.assertEqual(neoblock.annotations["nix_name"], nixname)

    def test_index_read(self):
        for idx, nixblock in enumerate(self.nixfile.blocks):
            neoblock = self.io.read_block(index=idx)
            self.assertEqual(neoblock.annotations["nix_name"], nixblock.name)

    def test_auto_index_read(self):
        for nixblock in self.nixfile.blocks:
            neoblock = self.io.read_block()  # don't specify index
            self.assertEqual(neoblock.annotations["nix_name"], nixblock.name)

        # No more blocks - should return None
        self.assertIs(self.io.read_block(), None)
        self.assertIs(self.io.read_block(), None)
        self.assertIs(self.io.read_block(), None)

    def test_neo_name_read(self):
        for nixblock in self.nixfile.blocks:
            neoname = nixblock.metadata["neo_name"]
            neoblock = self.io.read_block(neoname=neoname)
            self.assertEqual(neoblock.annotations["nix_name"], nixblock.name)
Beispiel #4
0
 def setUp(self):
     self.tempdir = mkdtemp(prefix="nixiotest")
     self.filename = os.path.join(self.tempdir, "testnixio.nix")
     self.writer = NixIO(self.filename, "ow")
     self.io = self.writer
     self.reader = nix.File.open(self.filename,
                                 nix.FileMode.ReadOnly,
                                 backend="h5py")
Beispiel #5
0
 def setUp(self):
     super().setUp()
     self.testfilename = self.get_local_path('nix/nixio_fr.nix')
     self.reader_fr = NixIOfr(filename=self.testfilename)
     self.reader_norm = NixIO(filename=self.testfilename, mode='ro')
     self.blk = self.reader_fr.read_block(block_index=1, load_waveforms=True)
     # read block with NixIOfr
     self.blk1 = self.reader_norm.read_block(index=1)  # read same block with NixIO
Beispiel #6
0
    def test_file_with_ver(self):
        someversion = '0.100.10'
        nixfile = nix.File.open(self.filename, nix.FileMode.Overwrite)
        filemd = nixfile.create_section("neo", "neo.metadata")
        filemd["version"] = someversion
        nixfile.close()

        with NixIO(self.filename, "ro") as iofile:
            self.assertEqual(iofile._file_version, someversion)

        with NixIO(self.filename, "rw") as iofile:
            self.assertEqual(iofile._file_version, someversion)

        with NixIO(self.filename, "ow") as iofile:
            self.assertEqual(iofile._file_version, neover)
Beispiel #7
0
 def test_annotations(self):
     self.testfilename = self.get_filename_path('nixio_fr_ann.nix')
     with NixIO(filename=self.testfilename, mode='ow') as io:
         annotations = {'my_custom_annotation': 'hello block'}
         bl = Block(**annotations)
         annotations = {'something': 'hello hello000'}
         seg = Segment(**annotations)
         an =AnalogSignal([[1, 2, 3], [4, 5, 6]], units='V',
                                     sampling_rate=1*pq.Hz)
         an.annotations['ansigrandom'] = 'hello chars'
         sp = SpikeTrain([3, 4, 5]* s, t_stop=10.0)
         sp.annotations['railway'] = 'hello train'
         ev = Event(np.arange(0, 30, 10)*pq.Hz,
                    labels=np.array(['trig0', 'trig1', 'trig2'], dtype='S'))
         ev.annotations['venue'] = 'hello event'
         ev2 = Event(np.arange(0, 30, 10) * pq.Hz,
                    labels=np.array(['trig0', 'trig1', 'trig2'], dtype='S'))
         ev2.annotations['evven'] = 'hello ev'
         seg.spiketrains.append(sp)
         seg.events.append(ev)
         seg.events.append(ev2)
         seg.analogsignals.append(an)
         bl.segments.append(seg)
         io.write_block(bl)
         io.close()
     with NixIOfr(filename=self.testfilename) as frio:
         frbl = frio.read_block()
         assert 'my_custom_annotation' in frbl.annotations
         assert 'something' in frbl.segments[0].annotations
         # assert 'ansigrandom' in frbl.segments[0].analogsignals[0].annotations
         assert 'railway' in frbl.segments[0].spiketrains[0].annotations
         assert 'venue' in frbl.segments[0].events[0].annotations
         assert 'evven' in frbl.segments[0].events[1].annotations
     os.remove(self.testfilename)
Beispiel #8
0
 def setUp(self):
     self.filename = "nixio_testfile_write.h5"
     self.writer = NixIO(self.filename, "ow")
     self.io = self.writer
     self.reader = nix.File.open(self.filename,
                                 nix.FileMode.ReadOnly,
                                 backend="h5py")
Beispiel #9
0
    def test_new_file(self):
        with NixIO(self.filename, "ow") as iofile:
            self.assertEqual(iofile._file_version, neover)

        nixfile = nix.File.open(self.filename, nix.FileMode.ReadOnly)
        filever = nixfile.sections["neo"]["version"]
        self.assertEqual(filever, neover)
        nixfile.close()
Beispiel #10
0
 def setUp(self):
     super(TestNixfr, self).setUp()
     self.testfilename = self.get_filename_path('nixio_fr.nix')
     self.reader_fr = NixIOfr(filename=self.testfilename)
     self.reader_norm = NixIO(filename=self.testfilename, mode='ro')
     self.blk = self.reader_fr.read_block(block_index=1, load_waveforms=True)
     # read block with NixIOfr
     self.blk1 = self.reader_norm.read_block(index=1)  # read same block with NixIO
Beispiel #11
0
    def test_oldfile_nover(self):
        nixfile = nix.File.open(self.filename, nix.FileMode.Overwrite)
        nixfile.close()
        with NixIO(self.filename, "ro") as iofile:
            self.assertEqual(iofile._file_version, '0.5.2')  # compat version

        nixfile = nix.File.open(self.filename, nix.FileMode.ReadOnly)
        self.assertNotIn("neo", nixfile.sections)
        nixfile.close()

        with NixIO(self.filename, "rw") as iofile:
            self.assertEqual(iofile._file_version, '0.5.2')  # compat version

        # section should have been created now
        nixfile = nix.File.open(self.filename, nix.FileMode.ReadOnly)
        self.assertIn("neo", nixfile.sections)
        self.assertEqual(nixfile.sections["neo"]["version"], '0.5.2')
        nixfile.close()
Beispiel #12
0
    def test_context_write(self):
        neoblock = Block(name=self.rword(), description=self.rsentence())
        with NixIO(self.filename, "ow") as iofile:
            iofile.write_block(neoblock)

        nixfile = nix.File.open(self.filename, nix.FileMode.ReadOnly,
                                backend="h5py")
        self.compare_blocks([neoblock], nixfile.blocks)
        nixfile.close()

        neoblock.annotate(**self.rdict(5))
        with NixIO(self.filename, "rw") as iofile:
            iofile.write_block(neoblock)
        nixfile = nix.File.open(self.filename, nix.FileMode.ReadOnly,
                                backend="h5py")
        self.compare_blocks([neoblock], nixfile.blocks)
        nixfile.close()
        os.remove(self.filename)
Beispiel #13
0
    def test_no_segment_write(self):
        # Tests storing AnalogSignal, IrregularlySampledSignal, and SpikeTrain
        # objects in the secondary (ChannelIndex) substructure without them
        # being attached to a Segment.
        blk = Block("segmentless block")
        signal = AnalogSignal(name="sig1",
                              signal=[0, 1, 2],
                              units="mV",
                              sampling_period=pq.Quantity(1, "ms"))
        othersignal = IrregularlySampledSignal(name="i1",
                                               signal=[0, 0, 0],
                                               units="mV",
                                               times=[1, 2, 3],
                                               time_units="ms")
        sta = SpikeTrain(name="the train of spikes",
                         times=[0.1, 0.2, 10.3],
                         t_stop=11,
                         units="us")
        stb = SpikeTrain(name="the train of spikes b",
                         times=[1.1, 2.2, 10.1],
                         t_stop=100,
                         units="ms")

        chidx = ChannelIndex([8, 13, 21])
        blk.channel_indexes.append(chidx)
        chidx.analogsignals.append(signal)
        chidx.irregularlysampledsignals.append(othersignal)

        unit = Unit()
        chidx.units.append(unit)
        unit.spiketrains.extend([sta, stb])
        self.writer.write_block(blk)

        self.compare_blocks([blk], self.reader.blocks)

        self.writer.close()
        reader = NixIO(self.filename, "ro")
        blk = reader.read_block(neoname="segmentless block")
        chx = blk.channel_indexes[0]
        self.assertEqual(len(chx.analogsignals), 1)
        self.assertEqual(len(chx.irregularlysampledsignals), 1)
        self.assertEqual(len(chx.units[0].spiketrains), 2)
Beispiel #14
0
def dump_electrode_data_circus(in_filename, out_filename, chunks=1e9):
    in_file = NixIO(in_filename)
    block = in_file.read_all_blocks()[0]
    signals = block.segments[2].analogsignals
    names = [signal.annotations['nix_name'] for signal in signals]

    indices = sorted(range(len(signals)), key=lambda x: names[x])
    signals = [signals[i] for i in indices]
    names = [names[i] for i in indices]

    itemsize = np.array([0.0], dtype=np.float32).nbytes

    n = len(signals[0])  # num samples per channel
    n_items = int(chunks // itemsize)  # num chunked samples per chan
    total_n = sum(len(value) for value in signals)  # num samples total
    pbar = tqdm(total=total_n * itemsize,
                file=sys.stdout,
                unit_scale=1,
                unit='bytes')

    mmap_array = open_memmap(out_filename,
                             mode='w+',
                             dtype=np.float32,
                             shape=(n, len(signals)))

    for k, signal in enumerate(signals):
        i = 0
        n = len(signal)

        while i * n_items < n:
            items = np.array(signal[i * n_items:min((i + 1) * n_items, n)],
                             dtype=np.float32)[:, 0]
            mmap_array[i * n_items:i * n_items + len(items), k] = items
            pbar.update(len(items) * itemsize)
            i += 1
    pbar.close()
    print('Channel order is: {}'.format(names))
Beispiel #15
0
    def test_context_read(self):
        nixfile = nix.File.open(self.filename,
                                nix.FileMode.Overwrite,
                                backend="h5py")
        name_one = self.rword()
        name_two = self.rword()
        nixfile.create_block(name_one, "neo.block")
        nixfile.create_block(name_two, "neo.block")
        nixfile.close()

        with NixIO(self.filename, "ro") as iofile:
            blocks = iofile.read_all_blocks()

        self.assertEqual(blocks[0].name, name_one)
        self.assertEqual(blocks[1].name, name_two)
Beispiel #16
0
class NixIOReadTest(NixIOTest):

    filename = "testfile_readtest.h5"
    nixfile = None
    nix_blocks = None
    original_methods = dict()

    @classmethod
    def setUpClass(cls):
        if HAVE_NIX:
            cls.nixfile = cls.create_full_nix_file(cls.filename)

    def setUp(self):
        self.io = NixIO(self.filename, "ro")
        self.original_methods["_read_cascade"] = self.io._read_cascade
        self.original_methods["_update_maps"] = self.io._update_maps

    @classmethod
    def tearDownClass(cls):
        if HAVE_NIX:
            cls.nixfile.close()

    def tearDown(self):
        self.io.close()

    def test_all_read(self):
        neo_blocks = self.io.read_all_blocks(cascade=True, lazy=False)
        nix_blocks = self.io.nix_file.blocks
        self.compare_blocks(neo_blocks, nix_blocks)

    def test_lazyload_fullcascade_read(self):
        neo_blocks = self.io.read_all_blocks(cascade=True, lazy=True)
        nix_blocks = self.io.nix_file.blocks
        # data objects should be empty
        for block in neo_blocks:
            for seg in block.segments:
                for asig in seg.analogsignals:
                    self.assertEqual(len(asig), 0)
                for isig in seg.irregularlysampledsignals:
                    self.assertEqual(len(isig), 0)
                for epoch in seg.epochs:
                    self.assertEqual(len(epoch), 0)
                for event in seg.events:
                    self.assertEqual(len(event), 0)
                for st in seg.spiketrains:
                    self.assertEqual(len(st), 0)
        self.compare_blocks(neo_blocks, nix_blocks)

    def test_lazyload_lazycascade_read(self):
        neo_blocks = self.io.read_all_blocks(cascade="lazy", lazy=True)
        nix_blocks = self.io.nix_file.blocks
        self.compare_blocks(neo_blocks, nix_blocks)

    def test_lazycascade_read(self):
        def getitem(self, index):
            return self._data.__getitem__(index)

        from neo.io.nixio import LazyList
        getitem_original = LazyList.__getitem__
        LazyList.__getitem__ = getitem
        neo_blocks = self.io.read_all_blocks(cascade="lazy", lazy=False)
        for block in neo_blocks:
            self.assertIsInstance(block.segments, LazyList)
            self.assertIsInstance(block.channel_indexes, LazyList)
            for seg in block.segments:
                self.assertIsInstance(seg, string_types)
            for chx in block.channel_indexes:
                self.assertIsInstance(chx, string_types)
        LazyList.__getitem__ = getitem_original

    def test_load_lazy_cascade(self):
        from neo.io.nixio import LazyList
        neo_blocks = self.io.read_all_blocks(cascade="lazy", lazy=False)
        for block in neo_blocks:
            self.assertIsInstance(block.segments, LazyList)
            self.assertIsInstance(block.channel_indexes, LazyList)
            name = block.name
            block = self.io.load_lazy_cascade("/" + name, lazy=False)
            self.assertIsInstance(block.segments, list)
            self.assertIsInstance(block.channel_indexes, list)
            for seg in block.segments:
                self.assertIsInstance(seg.analogsignals, list)
                self.assertIsInstance(seg.irregularlysampledsignals, list)
                self.assertIsInstance(seg.epochs, list)
                self.assertIsInstance(seg.events, list)
                self.assertIsInstance(seg.spiketrains, list)

    def test_nocascade_read(self):
        self.io._read_cascade = mock.Mock()
        neo_blocks = self.io.read_all_blocks(cascade=False)
        self.io._read_cascade.assert_not_called()
        for block in neo_blocks:
            self.assertEqual(len(block.segments), 0)
            nix_block = self.io.nix_file.blocks[block.name]
            self.compare_attr(block, nix_block)

    def test_lazy_load_subschema(self):
        blk = self.io.nix_file.blocks[0]
        segpath = "/" + blk.name + "/segments/" + blk.groups[0].name
        segment = self.io.load_lazy_cascade(segpath, lazy=True)
        self.assertIsInstance(segment, Segment)
        self.assertEqual(segment.name, blk.groups[0].name)
        self.assertIs(segment.block, None)
        self.assertEqual(len(segment.analogsignals[0]), 0)
        segment = self.io.load_lazy_cascade(segpath, lazy=False)
        self.assertEqual(np.shape(segment.analogsignals[0]), (100, 3))
Beispiel #17
0
    # random sampling times for data_b
    data_b_t = np.cumsum(np.random.random(1200))

    # Create one AnalogSignal and one IrregularlySampledSignal
    asig_a = AnalogSignal(name="Data A",
                          signal=data_a,
                          units="mV",
                          sampling_rate=pq.Quantity(10, "Hz"))
    isig_a = IrregularlySampledSignal(name="Sampled data",
                                      signal=data_b,
                                      units="nA",
                                      times=data_b_t,
                                      time_units="ms")

    # Attach the signals to the first segment
    seg_a.analogsignals.append(asig_a)
    seg_a.irregularlysampledsignals.append(isig_a)

    # Create a second AnalogSignal and attach it to the second segment
    st_a = AnalogSignal(name="Data A",
                        signal=data_c * pq.mV,
                        sampling_rate=20 * pq.Hz)
    seg_b.analogsignals.append(st_a)

# Write the Block to file using the NixIO
# Replace NixIO with any other IO to change storage format
io = NixIO("example-file.nix", mode='ow')
io.write_block(block)

io.close()
Beispiel #18
0
class NixIOWriteTest(NixIOTest):
    def setUp(self):
        self.filename = "nixio_testfile_write.h5"
        self.writer = NixIO(self.filename, "ow")
        self.io = self.writer
        self.reader = nix.File.open(self.filename,
                                    nix.FileMode.ReadOnly,
                                    backend="h5py")

    def tearDown(self):
        self.writer.close()
        self.reader.close()
        os.remove(self.filename)

    def write_and_compare(self, blocks):
        self.writer.write_all_blocks(blocks)
        self.compare_blocks(self.writer.read_all_blocks(), self.reader.blocks)

    def test_block_write(self):
        block = Block(name=self.rword(), description=self.rsentence())
        self.write_and_compare([block])

        block.annotate(**self.rdict(5))
        self.write_and_compare([block])

    def test_segment_write(self):
        block = Block(name=self.rword())
        segment = Segment(name=self.rword(), description=self.rword())
        block.segments.append(segment)
        self.write_and_compare([block])

        segment.annotate(**self.rdict(2))
        self.write_and_compare([block])

    def test_channel_index_write(self):
        block = Block(name=self.rword())
        chx = ChannelIndex(name=self.rword(),
                           description=self.rsentence(),
                           index=[1, 2, 3, 5, 8, 13])
        block.channel_indexes.append(chx)
        self.write_and_compare([block])

        chx.annotate(**self.rdict(3))
        self.write_and_compare([block])

    def test_signals_write(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        asig = AnalogSignal(signal=self.rquant((10, 3), pq.mV),
                            sampling_rate=pq.Quantity(10, "Hz"))
        seg.analogsignals.append(asig)
        self.write_and_compare([block])

        anotherblock = Block("ir signal block")
        seg = Segment("ir signal seg")
        anotherblock.segments.append(seg)
        irsig = IrregularlySampledSignal(signal=np.random.random((20, 3)),
                                         times=self.rquant(20, pq.ms, True),
                                         units=pq.A)
        seg.irregularlysampledsignals.append(irsig)
        self.write_and_compare([anotherblock])

        block.segments[0].analogsignals.append(
            AnalogSignal(signal=[10.0, 1.0, 3.0],
                         units=pq.S,
                         sampling_period=pq.Quantity(3, "s"),
                         dtype=np.double,
                         name="signal42",
                         description="this is an analogsignal",
                         t_start=45 * pq.ms), )
        self.write_and_compare([block, anotherblock])

        block.segments[0].irregularlysampledsignals.append(
            IrregularlySampledSignal(times=np.random.random(10),
                                     signal=np.random.random((10, 3)),
                                     units="mV",
                                     time_units="s",
                                     dtype=np.float,
                                     name="some sort of signal",
                                     description="the signal is described"))
        self.write_and_compare([block, anotherblock])

    def test_epoch_write(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        epoch = Epoch(times=[1, 1, 10, 3] * pq.ms,
                      durations=[3, 3, 3, 1] * pq.ms,
                      labels=np.array(["one", "two", "three", "four"]),
                      name="test epoch",
                      description="an epoch for testing")

        seg.epochs.append(epoch)
        self.write_and_compare([block])

    def test_event_write(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        event = Event(times=np.arange(0, 30, 10) * pq.s,
                      labels=np.array(["0", "1", "2"]),
                      name="event name",
                      description="event description")
        seg.events.append(event)
        self.write_and_compare([block])

    def test_spiketrain_write(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        spiketrain = SpikeTrain(times=[3, 4, 5] * pq.s,
                                t_stop=10.0,
                                name="spikes!",
                                description="sssssspikes")
        seg.spiketrains.append(spiketrain)
        self.write_and_compare([block])

        waveforms = self.rquant((3, 5, 10), pq.mV)
        spiketrain = SpikeTrain(times=[1, 1.1, 1.2] * pq.ms,
                                t_stop=1.5 * pq.s,
                                name="spikes with wf",
                                description="spikes for waveform test",
                                waveforms=waveforms)

        seg.spiketrains.append(spiketrain)
        self.write_and_compare([block])

        spiketrain.left_sweep = np.random.random(10) * pq.ms
        self.write_and_compare([block])

    def test_metadata_structure_write(self):
        neoblk = self.create_all_annotated()
        self.io.write_block(neoblk)
        blk = self.io.nix_file.blocks[0]

        blkmd = blk.metadata
        self.assertEqual(blk.name, blkmd.name)

        grp = blk.groups[0]  # segment
        self.assertIn(grp.name, blkmd.sections)

        grpmd = blkmd.sections[grp.name]
        for da in grp.data_arrays:  # signals
            name = ".".join(da.name.split(".")[:-1])
            self.assertIn(name, grpmd.sections)
        for mtag in grp.multi_tags:  # spiketrains, events, and epochs
            self.assertIn(mtag.name, grpmd.sections)

        srcchx = blk.sources[0]  # chx
        self.assertIn(srcchx.name, blkmd.sections)

        for srcunit in blk.sources:  # units
            self.assertIn(srcunit.name, blkmd.sections)

        self.write_and_compare([neoblk])

    def test_anonymous_objects_write(self):
        nblocks = 2
        nsegs = 2
        nanasig = 4
        nirrseg = 2
        nepochs = 3
        nevents = 4
        nspiketrains = 3
        nchx = 5
        nunits = 10

        times = self.rquant(1, pq.s)
        signal = self.rquant(1, pq.V)
        blocks = []
        for blkidx in range(nblocks):
            blk = Block()
            blocks.append(blk)
            for segidx in range(nsegs):
                seg = Segment()
                blk.segments.append(seg)
                for anaidx in range(nanasig):
                    seg.analogsignals.append(
                        AnalogSignal(signal=signal, sampling_rate=pq.Hz))
                for irridx in range(nirrseg):
                    seg.irregularlysampledsignals.append(
                        IrregularlySampledSignal(times=times,
                                                 signal=signal,
                                                 time_units=pq.s))
                for epidx in range(nepochs):
                    seg.epochs.append(Epoch(times=times, durations=times))
                for evidx in range(nevents):
                    seg.events.append(Event(times=times))
                for stidx in range(nspiketrains):
                    seg.spiketrains.append(
                        SpikeTrain(times=times, t_stop=pq.s, units=pq.s))
            for chidx in range(nchx):
                chx = ChannelIndex(name="chx{}".format(chidx), index=[1, 2])
                blk.channel_indexes.append(chx)
                for unidx in range(nunits):
                    unit = Unit()
                    chx.units.append(unit)
        self.writer.write_all_blocks(blocks)
        self.compare_blocks(blocks, self.reader.blocks)

    def test_to_value(self):
        section = self.io.nix_file.create_section("Metadata value test",
                                                  "Test")
        writeprop = self.io._write_property

        # quantity
        qvalue = pq.Quantity(10, "mV")
        writeprop(section, "qvalue", qvalue)
        self.assertEqual(section["qvalue"], 10)
        self.assertEqual(section.props["qvalue"].unit, "mV")

        # datetime
        dt = self.rdate()
        writeprop(section, "dt", dt)
        self.assertEqual(datetime.fromtimestamp(section["dt"]), dt)

        # string
        randstr = self.rsentence()
        writeprop(section, "randstr", randstr)
        self.assertEqual(section["randstr"], randstr)

        # bytes
        bytestring = b"bytestring"
        writeprop(section, "randbytes", bytestring)
        self.assertEqual(section["randbytes"], bytestring.decode())

        # iterables
        randlist = np.random.random(10).tolist()
        writeprop(section, "randlist", randlist)
        self.assertEqual(randlist, section["randlist"])

        randarray = np.random.random(10)
        writeprop(section, "randarray", randarray)
        np.testing.assert_almost_equal(randarray, section["randarray"])

        # numpy item
        npval = np.float64(2398)
        writeprop(section, "npval", npval)
        self.assertEqual(npval, section["npval"])

        # number
        val = 42
        writeprop(section, "val", val)
        self.assertEqual(val, section["val"])
Beispiel #19
0
 def setUp(self):
     self.io = NixIO(self.filename, "rw")
     self.neo_blocks = self.io.read_all_blocks()
     self.original_methods["_write_attr_annotations"] =\
         self.io._write_attr_annotations
Beispiel #20
0
class TestNixfr(BaseTestIO, unittest.TestCase, ):
    ioclass = NixIOfr

    entities_to_download = [
        'nix/nixio_fr.nix'
    ]
    entities_to_test = [
        'nix/nixio_fr.nix'
    ]

    def setUp(self):
        super().setUp()
        self.testfilename = self.get_local_path('nix/nixio_fr.nix')
        self.reader_fr = NixIOfr(filename=self.testfilename)
        self.reader_norm = NixIO(filename=self.testfilename, mode='ro')
        self.blk = self.reader_fr.read_block(block_index=1, load_waveforms=True)
        # read block with NixIOfr
        self.blk1 = self.reader_norm.read_block(index=1)  # read same block with NixIO

    def tearDown(self):
        self.reader_fr.file.close()
        self.reader_norm.close()

    def test_check_same_neo_structure(self):
        self.assertEqual(len(self.blk.segments), len(self.blk1.segments))
        for seg1, seg2 in zip(self.blk.segments, self.blk1.segments):
            self.assertEqual(len(seg1.analogsignals), len(seg2.analogsignals))
            self.assertEqual(len(seg1.spiketrains), len(seg2.spiketrains))
            self.assertEqual(len(seg1.events), len(seg2.events))
            self.assertEqual(len(seg1.epochs), len(seg2.epochs))

    def test_check_same_data_content(self):
        for seg1, seg2 in zip(self.blk.segments, self.blk1.segments):
            for asig1, asig2 in zip(seg1.analogsignals, seg2.analogsignals):
                np.testing.assert_almost_equal(asig1.magnitude, asig2.magnitude)
                # not completely equal
            for st1, st2 in zip(seg1.spiketrains, seg2.spiketrains):
                np.testing.assert_array_equal(st1.magnitude, st2.times)
                for wf1, wf2 in zip(st1.waveforms, st2.waveforms):
                    np.testing.assert_array_equal(wf1.shape, wf2.shape)
                    np.testing.assert_almost_equal(wf1.magnitude, wf2.magnitude)
            for ev1, ev2 in zip(seg1.events, seg2.events):
                np.testing.assert_almost_equal(ev1.times, ev2.times)
                assert np.all(ev1.labels == ev2.labels)
            for ep1, ep2 in zip(seg1.epochs, seg2.epochs):
                assert len(ep1.durations) == len(ep2.times)
                np.testing.assert_almost_equal(ep1.times, ep2.times)
                np.testing.assert_array_equal(ep1.durations, ep2.durations)
                np.testing.assert_array_equal(ep1.labels, ep2.labels)

    def test_analog_signal(self):
        seg1 = self.blk.segments[0]
        an_sig1 = seg1.analogsignals[0]
        assert len(an_sig1) == 30
        an_sig2 = seg1.analogsignals[1]
        assert an_sig2.shape == (50, 3)

    def test_spike_train(self):
        st1 = self.blk.segments[0].spiketrains[0]
        assert np.all(st1.times == np.cumsum(np.arange(0, 1, 0.1)).tolist() * pq.s + 10 * pq.s)

    def test_event(self):
        seg1 = self.blk.segments[0]
        event1 = seg1.events[0]
        raw_time = 10 + np.cumsum(np.array([0, 1, 2, 3, 4]))
        assert np.all(event1.times == np.array(raw_time * pq.s / 1000))
        assert np.all(event1.labels == np.array(['A', 'B', 'C', 'D', 'E'], dtype='U'))
        assert len(seg1.events) == 1

    def test_epoch(self):
        seg1 = self.blk.segments[1]
        seg2 = self.blk1.segments[1]
        epoch1 = seg1.epochs[0]
        epoch2 = seg2.epochs[0]
        assert len(epoch1.durations) == len(epoch1.times)
        assert np.all(epoch1.durations == epoch2.durations)
        assert np.all(epoch1.labels == epoch2.labels)

    def test_annotations(self):
        self.testfilename = self.get_local_path('nix/nixio_fr_ann.nix')
        with NixIO(filename=self.testfilename, mode='ow') as io:
            annotations = {'my_custom_annotation': 'hello block'}
            bl = Block(**annotations)
            annotations = {'something': 'hello hello000'}
            seg = Segment(**annotations)
            an =AnalogSignal([[1, 2, 3], [4, 5, 6]], units='V',
                             sampling_rate=1 * pq.Hz)
            an.annotate(ansigrandom='hello chars')
            an.array_annotate(custom_id=[1, 2, 3])
            sp = SpikeTrain([3, 4, 5]* s, t_stop=10.0)
            sp.annotations['railway'] = 'hello train'
            ev = Event(np.arange(0, 30, 10)*pq.Hz,
                       labels=np.array(['trig0', 'trig1', 'trig2'], dtype='S'))
            ev.annotations['venue'] = 'hello event'
            ev2 = Event(np.arange(0, 30, 10) * pq.Hz,
                       labels=np.array(['trig0', 'trig1', 'trig2'], dtype='S'))
            ev2.annotations['evven'] = 'hello ev'
            seg.spiketrains.append(sp)
            seg.events.append(ev)
            seg.events.append(ev2)
            seg.analogsignals.append(an)
            bl.segments.append(seg)
            io.write_block(bl)
            io.close()

        with NixIOfr(filename=self.testfilename) as frio:
            frbl = frio.read_block()
            assert 'my_custom_annotation' in frbl.annotations
            assert 'something' in frbl.segments[0].annotations
            assert 'ansigrandom' in frbl.segments[0].analogsignals[0].annotations
            assert 'railway' in frbl.segments[0].spiketrains[0].annotations
            assert 'venue' in frbl.segments[0].events[0].annotations
            assert 'evven' in frbl.segments[0].events[1].annotations
            assert 'custom_id' in frbl.segments[0].analogsignals[0].array_annotations
            for anasig in frbl.segments[0].analogsignals:
                for value in anasig.array_annotations.values():
                    assert anasig.shape[-1] == len(value)
        os.remove(self.testfilename)
Beispiel #21
0
class NixIOPartialWriteTest(NixIOTest):

    filename = "testfile_partialwrite.h5"
    nixfile = None
    neo_blocks = None
    original_methods = dict()

    @classmethod
    def setUpClass(cls):
        if HAVE_NIX:
            cls.nixfile = cls.create_full_nix_file(cls.filename)

    def setUp(self):
        self.io = NixIO(self.filename, "rw")
        self.neo_blocks = self.io.read_all_blocks()
        self.original_methods["_write_attr_annotations"] =\
            self.io._write_attr_annotations

    @classmethod
    def tearDownClass(cls):
        if HAVE_NIX:
            cls.nixfile.close()

    def tearDown(self):
        self.restore_methods()
        self.io.close()

    def restore_methods(self):
        for name, method in self.original_methods.items():
            setattr(self.io, name, self.original_methods[name])

    def _mock_write_attr(self, objclass):
        typestr = str(objclass.__name__).lower()
        self.io._write_attr_annotations = mock.Mock(
            wraps=self.io._write_attr_annotations,
            side_effect=self.check_obj_type("neo.{}".format(typestr)))
        neo_blocks = self.neo_blocks
        self.modify_objects(neo_blocks, excludes=[objclass])
        self.io.write_all_blocks(neo_blocks)
        self.restore_methods()

    def check_obj_type(self, typestring):
        neq = self.assertNotEqual

        def side_effect_func(*args, **kwargs):
            obj = kwargs.get("nixobj", args[0])
            if isinstance(obj, list):
                for sig in obj:
                    neq(sig.type, typestring)
            else:
                neq(obj.type, typestring)

        return side_effect_func

    @classmethod
    def modify_objects(cls, objs, excludes=()):
        excludes = tuple(excludes)
        for obj in objs:
            if not (excludes and isinstance(obj, excludes)):
                obj.description = cls.rsentence()
            for container in getattr(obj, "_child_containers", []):
                children = getattr(obj, container)
                cls.modify_objects(children, excludes)

    def test_partial(self):
        for objclass in NixIO.supported_objects:
            self._mock_write_attr(objclass)
            self.compare_blocks(self.neo_blocks, self.io.nix_file.blocks)

    def test_no_modifications(self):
        self.io._write_attr_annotations = mock.Mock()

        self.io.write_all_blocks(self.neo_blocks)
        self.io._write_attr_annotations.assert_not_called()
        self.compare_blocks(self.neo_blocks, self.io.nix_file.blocks)

        # clearing hashes and checking again
        for k in self.io._object_hashes.keys():
            self.io._object_hashes[k] = None
        self.io.write_all_blocks(self.neo_blocks)
        self.io._write_attr_annotations.assert_not_called()

        # changing hashes to force rewrite
        for k in self.io._object_hashes.keys():
            self.io._object_hashes[k] = "_"
        self.io.write_all_blocks(self.neo_blocks)
        callcount = self.io._write_attr_annotations.call_count
        self.assertEqual(callcount, len(self.io._object_hashes))
        self.compare_blocks(self.neo_blocks, self.io.nix_file.blocks)
class TestNixfr(BaseTestIO, unittest.TestCase, ):
    ioclass = NixIOfr

    files_to_test = ['nixio_fr.nix']

    files_to_download = ['nixio_fr.nix']

    def setUp(self):
        super(TestNixfr, self).setUp()
        self.testfilename = self.get_filename_path('nixio_fr.nix')
        self.reader_fr = NixIOfr(filename=self.testfilename)
        self.reader_norm = NixIO(filename=self.testfilename, mode='ro')
        self.blk = self.reader_fr.read_block(block_index=1, load_waveforms=True)
        # read block with NixIOfr
        self.blk1 = self.reader_norm.read_block(index=1)  # read same block with NixIO

    def tearDown(self):
        self.reader_fr.file.close()
        self.reader_norm.close()

    def test_check_same_neo_structure(self):
        self.assertEqual(len(self.blk.segments), len(self.blk1.segments))
        for seg1, seg2 in zip(self.blk.segments, self.blk1.segments):
            self.assertEqual(len(seg1.analogsignals), len(seg2.analogsignals))
            self.assertEqual(len(seg1.spiketrains), len(seg2.spiketrains))
            self.assertEqual(len(seg1.events), len(seg2.events))
            self.assertEqual(len(seg1.epochs), len(seg2.epochs))

    def test_check_same_data_content(self):
        for seg1, seg2 in zip(self.blk.segments, self.blk1.segments):
            for asig1, asig2 in zip(seg1.analogsignals, seg2.analogsignals):
                np.testing.assert_almost_equal(asig1.magnitude, asig2.magnitude)
                # not completely equal
            for st1, st2 in zip(seg1.spiketrains, seg2.spiketrains):
                np.testing.assert_array_equal(st1.magnitude, st2.times)
                for wf1, wf2 in zip(st1.waveforms, st2.waveforms):
                    np.testing.assert_array_equal(wf1.shape, wf2.shape)
                    np.testing.assert_almost_equal(wf1.magnitude, wf2.magnitude)
            for ev1, ev2 in zip(seg1.events, seg2.events):
                np.testing.assert_almost_equal(ev1.times, ev2.times)
                assert np.all(ev1.labels == ev2.labels)
            for ep1, ep2 in zip(seg1.epochs, seg2.epochs):
                assert len(ep1.durations) == len(ep2.times)
                np.testing.assert_almost_equal(ep1.times, ep2.times)
                np.testing.assert_array_equal(ep1.durations, ep2.durations)
                np.testing.assert_array_equal(ep1.labels, ep2.labels)

        # Not testing for channel_index as rawio always read from seg
        for chid1, chid2 in zip(self.blk.channel_indexes, self.blk1.channel_indexes):
            for asig1, asig2 in zip(chid1.analogsignals, chid2.analogsignals):
                np.testing.assert_almost_equal(asig1.magnitude, asig2.magnitude)

    def test_analog_signal(self):
        seg1 = self.blk.segments[0]
        an_sig1 = seg1.analogsignals[0]
        assert len(an_sig1) == 30
        an_sig2 = seg1.analogsignals[1]
        assert an_sig2.shape == (50, 3)

    def test_spike_train(self):
        st1 = self.blk.segments[0].spiketrains[0]
        assert np.all(st1.times == np.cumsum(np.arange(0, 1, 0.1)).tolist() * pq.s + 10 * pq.s)

    def test_event(self):
        seg1 = self.blk.segments[0]
        event1 = seg1.events[0]
        raw_time = 10 + np.cumsum(np.array([0, 1, 2, 3, 4]))
        assert np.all(event1.times == np.array(raw_time * pq.s / 1000))
        assert np.all(event1.labels == np.array([b'A', b'B', b'C', b'D', b'E']))
        assert len(seg1.events) == 1

    def test_epoch(self):
        seg1 = self.blk.segments[1]
        seg2 = self.blk1.segments[1]
        epoch1 = seg1.epochs[0]
        epoch2 = seg2.epochs[0]
        assert len(epoch1.durations) == len(epoch1.times)
        assert np.all(epoch1.durations == epoch2.durations)
        assert np.all(epoch1.labels == epoch2.labels)
Beispiel #23
0
class NixIOReadTest(NixIOTest):

    filename = "testfile_readtest.h5"
    nixfile = None
    nix_blocks = None
    original_methods = dict()

    @classmethod
    def setUpClass(cls):
        if HAVE_NIX:
            cls.nixfile = cls.create_full_nix_file(cls.filename)

    def setUp(self):
        self.io = NixIO(self.filename, "ro")
        self.original_methods["_read_cascade"] = self.io._read_cascade
        self.original_methods["_update_maps"] = self.io._update_maps

    @classmethod
    def tearDownClass(cls):
        if HAVE_NIX:
            cls.nixfile.close()
            os.remove(cls.filename)

    def tearDown(self):
        self.io.close()

    def test_all_read(self):
        neo_blocks = self.io.read_all_blocks(cascade=True, lazy=False)
        nix_blocks = self.io.nix_file.blocks
        self.compare_blocks(neo_blocks, nix_blocks)

    def test_lazyload_fullcascade_read(self):
        neo_blocks = self.io.read_all_blocks(cascade=True, lazy=True)
        nix_blocks = self.io.nix_file.blocks
        # data objects should be empty
        for block in neo_blocks:
            for seg in block.segments:
                for asig in seg.analogsignals:
                    self.assertEqual(len(asig), 0)
                for isig in seg.irregularlysampledsignals:
                    self.assertEqual(len(isig), 0)
                for epoch in seg.epochs:
                    self.assertEqual(len(epoch), 0)
                for event in seg.events:
                    self.assertEqual(len(event), 0)
                for st in seg.spiketrains:
                    self.assertEqual(len(st), 0)
        self.compare_blocks(neo_blocks, nix_blocks)

    def test_lazyload_lazycascade_read(self):
        neo_blocks = self.io.read_all_blocks(cascade="lazy", lazy=True)
        nix_blocks = self.io.nix_file.blocks
        self.compare_blocks(neo_blocks, nix_blocks)

    def test_lazycascade_read(self):
        def getitem(self, index):
            return self._data.__getitem__(index)
        from neo.io.nixio import LazyList
        getitem_original = LazyList.__getitem__
        LazyList.__getitem__ = getitem
        neo_blocks = self.io.read_all_blocks(cascade="lazy", lazy=False)
        for block in neo_blocks:
            self.assertIsInstance(block.segments, LazyList)
            self.assertIsInstance(block.channel_indexes, LazyList)
            for seg in block.segments:
                self.assertIsInstance(seg, string_types)
            for chx in block.channel_indexes:
                self.assertIsInstance(chx, string_types)
        LazyList.__getitem__ = getitem_original

    def test_load_lazy_cascade(self):
        from neo.io.nixio import LazyList
        neo_blocks = self.io.read_all_blocks(cascade="lazy", lazy=False)
        for block in neo_blocks:
            self.assertIsInstance(block.segments, LazyList)
            self.assertIsInstance(block.channel_indexes, LazyList)
            name = block.annotations["nix_name"]
            block = self.io.load_lazy_cascade("/" + name, lazy=False)
            self.assertIsInstance(block.segments, list)
            self.assertIsInstance(block.channel_indexes, list)
            for seg in block.segments:
                self.assertIsInstance(seg.analogsignals, list)
                self.assertIsInstance(seg.irregularlysampledsignals, list)
                self.assertIsInstance(seg.epochs, list)
                self.assertIsInstance(seg.events, list)
                self.assertIsInstance(seg.spiketrains, list)

    def test_nocascade_read(self):
        self.io._read_cascade = mock.Mock()
        neo_blocks = self.io.read_all_blocks(cascade=False)
        self.io._read_cascade.assert_not_called()
        for block in neo_blocks:
            self.assertEqual(len(block.segments), 0)
            nix_block = self.io.nix_file.blocks[block.annotations["nix_name"]]
            self.compare_attr(block, nix_block)

    def test_lazy_load_subschema(self):
        blk = self.io.nix_file.blocks[0]
        segpath = "/" + blk.name + "/segments/" + blk.groups[0].name
        segment = self.io.load_lazy_cascade(segpath, lazy=True)
        self.assertIsInstance(segment, Segment)
        self.assertEqual(segment.annotations["nix_name"], blk.groups[0].name)
        self.assertIs(segment.block, None)
        self.assertEqual(len(segment.analogsignals[0]), 0)
        segment = self.io.load_lazy_cascade(segpath, lazy=False)
        self.assertEqual(np.shape(segment.analogsignals[0]), (100, 3))
Beispiel #24
0
 def setUp(self):
     self.io = NixIO(self.filename, "rw")
     self.neo_blocks = self.io.read_all_blocks()
     self.original_methods["_write_attr_annotations"] =\
         self.io._write_attr_annotations
Beispiel #25
0
class NixIOWriteTest(NixIOTest):

    def setUp(self):
        self.filename = "nixio_testfile_write.h5"
        self.writer = NixIO(self.filename, "ow")
        self.io = self.writer
        self.reader = nix.File.open(self.filename,
                                    nix.FileMode.ReadOnly,
                                    backend="h5py")

    def tearDown(self):
        self.writer.close()
        self.reader.close()
        os.remove(self.filename)

    def write_and_compare(self, blocks):
        self.writer.write_all_blocks(blocks)
        self.compare_blocks(self.writer.read_all_blocks(), self.reader.blocks)
        self.compare_blocks(blocks, self.reader.blocks)

    def test_block_write(self):
        block = Block(name=self.rword(),
                      description=self.rsentence())
        self.write_and_compare([block])

        block.annotate(**self.rdict(5))
        self.write_and_compare([block])

    def test_segment_write(self):
        block = Block(name=self.rword())
        segment = Segment(name=self.rword(), description=self.rword())
        block.segments.append(segment)
        self.write_and_compare([block])

        segment.annotate(**self.rdict(2))
        self.write_and_compare([block])

    def test_channel_index_write(self):
        block = Block(name=self.rword())
        chx = ChannelIndex(name=self.rword(),
                           description=self.rsentence(),
                           channel_ids=[10, 20, 30, 50, 80, 130],
                           index=[1, 2, 3, 5, 8, 13])
        block.channel_indexes.append(chx)
        self.write_and_compare([block])

        chx.annotate(**self.rdict(3))
        self.write_and_compare([block])

        chx.channel_names = ["one", "two", "three", "five",
                             "eight", "xiii"]
        self.write_and_compare([block])

    def test_signals_write(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        asig = AnalogSignal(signal=self.rquant((10, 3), pq.mV),
                            sampling_rate=pq.Quantity(10, "Hz"))
        seg.analogsignals.append(asig)
        self.write_and_compare([block])

        anotherblock = Block("ir signal block")
        seg = Segment("ir signal seg")
        anotherblock.segments.append(seg)
        irsig = IrregularlySampledSignal(
            signal=np.random.random((20, 3)),
            times=self.rquant(20, pq.ms, True),
            units=pq.A
        )
        seg.irregularlysampledsignals.append(irsig)
        self.write_and_compare([block, anotherblock])

        block.segments[0].analogsignals.append(
            AnalogSignal(signal=[10.0, 1.0, 3.0], units=pq.S,
                         sampling_period=pq.Quantity(3, "s"),
                         dtype=np.double, name="signal42",
                         description="this is an analogsignal",
                         t_start=45 * pq.ms),
        )
        self.write_and_compare([block, anotherblock])

        block.segments[0].irregularlysampledsignals.append(
            IrregularlySampledSignal(times=np.random.random(10),
                                     signal=np.random.random((10, 3)),
                                     units="mV", time_units="s",
                                     dtype=np.float,
                                     name="some sort of signal",
                                     description="the signal is described")
        )
        self.write_and_compare([block, anotherblock])

    def test_epoch_write(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        epoch = Epoch(times=[1, 1, 10, 3]*pq.ms, durations=[3, 3, 3, 1]*pq.ms,
                      labels=np.array(["one", "two", "three", "four"]),
                      name="test epoch", description="an epoch for testing")

        seg.epochs.append(epoch)
        self.write_and_compare([block])

    def test_event_write(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        event = Event(times=np.arange(0, 30, 10)*pq.s,
                      labels=np.array(["0", "1", "2"]),
                      name="event name",
                      description="event description")
        seg.events.append(event)
        self.write_and_compare([block])

    def test_spiketrain_write(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        spiketrain = SpikeTrain(times=[3, 4, 5]*pq.s, t_stop=10.0,
                                name="spikes!", description="sssssspikes")
        seg.spiketrains.append(spiketrain)
        self.write_and_compare([block])

        waveforms = self.rquant((3, 5, 10), pq.mV)
        spiketrain = SpikeTrain(times=[1, 1.1, 1.2]*pq.ms, t_stop=1.5*pq.s,
                                name="spikes with wf",
                                description="spikes for waveform test",
                                waveforms=waveforms)

        seg.spiketrains.append(spiketrain)
        self.write_and_compare([block])

        spiketrain.left_sweep = np.random.random(10)*pq.ms
        self.write_and_compare([block])

    def test_metadata_structure_write(self):
        neoblk = self.create_all_annotated()
        self.io.write_block(neoblk)
        blk = self.io.nix_file.blocks[0]

        blkmd = blk.metadata
        self.assertEqual(blk.name, blkmd.name)

        grp = blk.groups[0]  # segment
        self.assertIn(grp.name, blkmd.sections)

        grpmd = blkmd.sections[grp.name]
        for da in grp.data_arrays:  # signals
            name = ".".join(da.name.split(".")[:-1])
            self.assertIn(name, grpmd.sections)
        for mtag in grp.multi_tags:  # spiketrains, events, and epochs
            self.assertIn(mtag.name, grpmd.sections)

        srcchx = blk.sources[0]  # chx
        self.assertIn(srcchx.name, blkmd.sections)

        for srcunit in blk.sources:  # units
            self.assertIn(srcunit.name, blkmd.sections)

        self.write_and_compare([neoblk])

    def test_anonymous_objects_write(self):
        nblocks = 2
        nsegs = 2
        nanasig = 4
        nirrseg = 2
        nepochs = 3
        nevents = 4
        nspiketrains = 3
        nchx = 5
        nunits = 10

        times = self.rquant(1, pq.s)
        signal = self.rquant(1, pq.V)
        blocks = []
        for blkidx in range(nblocks):
            blk = Block()
            blocks.append(blk)
            for segidx in range(nsegs):
                seg = Segment()
                blk.segments.append(seg)
                for anaidx in range(nanasig):
                    seg.analogsignals.append(AnalogSignal(signal=signal,
                                                          sampling_rate=pq.Hz))
                for irridx in range(nirrseg):
                    seg.irregularlysampledsignals.append(
                        IrregularlySampledSignal(times=times,
                                                 signal=signal,
                                                 time_units=pq.s)
                    )
                for epidx in range(nepochs):
                    seg.epochs.append(Epoch(times=times, durations=times))
                for evidx in range(nevents):
                    seg.events.append(Event(times=times))
                for stidx in range(nspiketrains):
                    seg.spiketrains.append(SpikeTrain(times=times,
                                                      t_stop=times[-1]+pq.s,
                                                      units=pq.s))
            for chidx in range(nchx):
                chx = ChannelIndex(name="chx{}".format(chidx),
                                   index=[1, 2],
                                   channel_ids=[11, 22])
                blk.channel_indexes.append(chx)
                for unidx in range(nunits):
                    unit = Unit()
                    chx.units.append(unit)
        self.writer.write_all_blocks(blocks)
        self.compare_blocks(blocks, self.reader.blocks)

    def test_multiref_write(self):
        blk = Block("blk1")
        signal = AnalogSignal(name="sig1", signal=[0, 1, 2], units="mV",
                              sampling_period=pq.Quantity(1, "ms"))

        for idx in range(3):
            segname = "seg" + str(idx)
            seg = Segment(segname)
            blk.segments.append(seg)
            seg.analogsignals.append(signal)

        chidx = ChannelIndex([10, 20, 29])
        seg = blk.segments[0]
        st = SpikeTrain(name="choochoo", times=[10, 11, 80], t_stop=1000,
                        units="s")
        seg.spiketrains.append(st)
        blk.channel_indexes.append(chidx)
        for idx in range(6):
            unit = Unit("unit" + str(idx))
            chidx.units.append(unit)
            unit.spiketrains.append(st)

        self.writer.write_block(blk)
        self.compare_blocks([blk], self.reader.blocks)

    def test_to_value(self):
        section = self.io.nix_file.create_section("Metadata value test",
                                                  "Test")
        writeprop = self.io._write_property

        # quantity
        qvalue = pq.Quantity(10, "mV")
        writeprop(section, "qvalue", qvalue)
        self.assertEqual(section["qvalue"], 10)
        self.assertEqual(section.props["qvalue"].unit, "mV")

        # datetime
        dt = self.rdate()
        writeprop(section, "dt", dt)
        self.assertEqual(datetime.fromtimestamp(section["dt"]), dt)

        # string
        randstr = self.rsentence()
        writeprop(section, "randstr", randstr)
        self.assertEqual(section["randstr"], randstr)

        # bytes
        bytestring = b"bytestring"
        writeprop(section, "randbytes", bytestring)
        self.assertEqual(section["randbytes"], bytestring.decode())

        # iterables
        randlist = np.random.random(10).tolist()
        writeprop(section, "randlist", randlist)
        self.assertEqual(randlist, section["randlist"])

        randarray = np.random.random(10)
        writeprop(section, "randarray", randarray)
        np.testing.assert_almost_equal(randarray, section["randarray"])

        # numpy item
        npval = np.float64(2398)
        writeprop(section, "npval", npval)
        self.assertEqual(npval, section["npval"])

        # number
        val = 42
        writeprop(section, "val", val)
        self.assertEqual(val, section["val"])
Beispiel #26
0
class NixIOPartialWriteTest(NixIOTest):

    filename = "testfile_partialwrite.h5"
    nixfile = None
    neo_blocks = None
    original_methods = dict()

    @classmethod
    def setUpClass(cls):
        if HAVE_NIX:
            cls.nixfile = cls.create_full_nix_file(cls.filename)

    def setUp(self):
        self.io = NixIO(self.filename, "rw")
        self.neo_blocks = self.io.read_all_blocks()
        self.original_methods["_write_attr_annotations"] =\
            self.io._write_attr_annotations

    @classmethod
    def tearDownClass(cls):
        if HAVE_NIX:
            cls.nixfile.close()
            os.remove(cls.filename)

    def tearDown(self):
        self.restore_methods()
        self.io.close()

    def restore_methods(self):
        for name, method in self.original_methods.items():
            setattr(self.io, name, self.original_methods[name])

    def _mock_write_attr(self, objclass):
        typestr = str(objclass.__name__).lower()
        self.io._write_attr_annotations = mock.Mock(
            wraps=self.io._write_attr_annotations,
            side_effect=self.check_obj_type("neo.{}".format(typestr))
        )
        neo_blocks = self.neo_blocks
        self.modify_objects(neo_blocks, excludes=[objclass])
        self.io.write_all_blocks(neo_blocks)
        self.restore_methods()

    def check_obj_type(self, typestring):
        neq = self.assertNotEqual

        def side_effect_func(*args, **kwargs):
            obj = kwargs.get("nixobj", args[0])
            if isinstance(obj, list):
                for sig in obj:
                    neq(sig.type, typestring)
            else:
                neq(obj.type, typestring)
        return side_effect_func

    @classmethod
    def modify_objects(cls, objs, excludes=()):
        excludes = tuple(excludes)
        for obj in objs:
            if not (excludes and isinstance(obj, excludes)):
                obj.description = cls.rsentence()
            for container in getattr(obj, "_child_containers", []):
                children = getattr(obj, container)
                cls.modify_objects(children, excludes)

    def test_partial(self):
        for objclass in NixIO.supported_objects:
            self._mock_write_attr(objclass)
            self.compare_blocks(self.neo_blocks, self.io.nix_file.blocks)

    def test_no_modifications(self):
        self.io._write_attr_annotations = mock.Mock()

        self.io.write_all_blocks(self.neo_blocks)
        self.io._write_attr_annotations.assert_not_called()
        self.compare_blocks(self.neo_blocks, self.io.nix_file.blocks)

        # clearing hashes and checking again
        for k in self.io._object_hashes.keys():
            self.io._object_hashes[k] = None
        self.io.write_all_blocks(self.neo_blocks)
        self.io._write_attr_annotations.assert_not_called()

        # changing hashes to force rewrite
        for k in self.io._object_hashes.keys():
            self.io._object_hashes[k] = "_"
        self.io.write_all_blocks(self.neo_blocks)
        callcount = self.io._write_attr_annotations.call_count
        self.assertEqual(callcount, len(self.io._object_hashes))
        self.compare_blocks(self.neo_blocks, self.io.nix_file.blocks)
Beispiel #27
0
 def setUp(self):
     self.io = NixIO(self.filename, "ro")
Beispiel #28
0
def create_nix_file(file_pat,
                    output=None,
                    signed=False,
                    rate=1,
                    electrode_scale=0.0104,
                    analog_scale=12.5122,
                    channels=channels,
                    chunks=256 * 1024 * 1024):
    '''The default resolution (i.e. voltage per bit) in uV '''
    filenames = sorted(glob(file_pat))

    dtype = np.int16 if signed else np.uint16
    N = len(channels)
    slice_size = N * 2
    chunks = chunks - chunks % slice_size  # round to equal blocks

    reader = read_files(filenames, dtype, chunks, slice_size)
    data = next(reader)

    if signed:
        af = lambda x: x.astype(np.float32) * analog_scale
        ef = lambda x: x.astype(np.float32) * electrode_scale
        df = lambda x: np.array(x, dtype=np.bool_)
    else:
        af = lambda x: (x.astype(np.float32) - 2**15) * analog_scale
        ef = lambda x: (x.astype(np.float32) - 2**15) * electrode_scale
        df = lambda x: np.array(x.astype(np.int32) - 2**15, dtype=np.bool_)

    analogs = [(i, ch) for i, ch in enumerate(channels) if ch.startswith('A')]
    digitals = [(i, ch) for i, ch in enumerate(channels) if ch.startswith('D')]
    electrodes = [(i, ch) for i, ch in enumerate(channels)
                  if not ch.startswith('D') and not ch.startswith('A')]

    groups = (('Analog', analogs, af, np.float32),
              ('Digital', digitals, df, np.bool_), ('Electrodes', electrodes,
                                                    ef, np.float32))

    if output is None:
        output = '{}.h5'.format(splitext(filenames[0])[0])
    ofile = NixIO(output, mode='ow')

    blk = Block()
    for group_name, channels, f, dtype in groups:
        seg = Segment(name=group_name)
        for slice_idx, chan_name in channels:
            seg.analogsignals.append(
                AnalogSignal(f(data[slice_idx::N]),
                             dtype=dtype,
                             units=uV,
                             sampling_rate=rate * Hz,
                             name=chan_name))
        blk.segments.append(seg)

    ofile.write_block(blk)
    nix_file = ofile.nix_file
    nix_groups = nix_file.blocks[0].groups

    for data in reader:
        for k, (group_name, channels, f, _) in enumerate(groups):
            data_arrays = nix_groups[k].data_arrays
            for i, (slice_idx, _) in enumerate(channels):
                # nix_file._h5file.flush()
                data_arrays[i].append(f(data[slice_idx::N]))

    nix_file.close()
    return output
Beispiel #29
0
 def setUp(self):
     self.io = NixIO(self.filename, "ro")
     self.original_methods["_read_cascade"] = self.io._read_cascade
     self.original_methods["_update_maps"] = self.io._update_maps
Beispiel #30
0
 def setUp(self):
     self.io = NixIO(self.filename, "ro")
     self.original_methods["_read_cascade"] = self.io._read_cascade
     self.original_methods["_update_maps"] = self.io._update_maps
Beispiel #31
0
        epoch_times = tstart + np.cumsum(np.array([0,1,2])) * pq.ms
        epoch = Epoch(name="Seg {} :: Epoch".format(idx),
                      times=epoch_times,
                      durations=np.array([0,1,2])*pq.ms,
                      labels=["A+", "B+", "C+"])
        seg.epochs.append(epoch)

        tstart = 10 *pq.s
        st_times = tstart + np.cumsum(np.arange(0,1,0.1)) * pq.s
        tstop = max(event_times[-1], epoch_times[-1], st_times[-1]) + 1 * pq.s
        st = SpikeTrain(name="Seg {} :: SpikeTrain".format(idx),
                        times=st_times, t_start=tstart, t_stop=tstop)
        wf = np.random.random((len(st_times), nchannels, 30)) * pq.mV
        st.waveforms = wf
        st.sampling_rate = sampling_rate

        seg.spiketrains.append(st)

        unit = Unit(name="unit-{}".format(idx))
        print(unit)
        unit.spiketrains.append(st)
        chx.units.append(unit)
# Write the Block to file using the NixIO
# Any existing file will be overwritten
fname = "test_case.nix"
io = NixIO(fname, "ow")
io.write_block(block1)
io.write_block(block2)
io.close()
Beispiel #32
0
class NixIOWriteTest(NixIOTest):
    def setUp(self):
        self.tempdir = mkdtemp(prefix="nixiotest")
        self.filename = os.path.join(self.tempdir, "testnixio.nix")
        self.writer = NixIO(self.filename, "ow")
        self.io = self.writer
        self.reader = nix.File.open(self.filename,
                                    nix.FileMode.ReadOnly,
                                    backend="h5py")

    def tearDown(self):
        self.writer.close()
        self.reader.close()
        shutil.rmtree(self.tempdir)

    def write_and_compare(self, blocks):
        self.writer.write_all_blocks(blocks)
        self.compare_blocks(blocks, self.reader.blocks)
        self.compare_blocks(self.writer.read_all_blocks(), self.reader.blocks)
        self.compare_blocks(blocks, self.reader.blocks)

    def test_block_write(self):
        block = Block(name=self.rword(), description=self.rsentence())
        self.write_and_compare([block])

        block.annotate(**self.rdict(5))
        self.write_and_compare([block])

    def test_segment_write(self):
        block = Block(name=self.rword())
        segment = Segment(name=self.rword(), description=self.rword())
        block.segments.append(segment)
        self.write_and_compare([block])

        segment.annotate(**self.rdict(2))
        self.write_and_compare([block])

    def test_channel_index_write(self):
        block = Block(name=self.rword())
        chx = ChannelIndex(name=self.rword(),
                           description=self.rsentence(),
                           channel_ids=[10, 20, 30, 50, 80, 130],
                           index=[1, 2, 3, 5, 8, 13])
        block.channel_indexes.append(chx)
        self.write_and_compare([block])

        chx.annotate(**self.rdict(3))
        self.write_and_compare([block])

        chx.channel_names = ["one", "two", "three", "five", "eight", "xiii"]

        chx.coordinates = self.rquant((6, 3), pq.um)
        self.write_and_compare([block])

        # add an empty channel index and check again
        newchx = ChannelIndex(np.array([]))
        block.channel_indexes.append(newchx)
        self.write_and_compare([block])

    def test_signals_write(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        asig = AnalogSignal(signal=self.rquant((10, 3), pq.mV),
                            sampling_rate=pq.Quantity(10, "Hz"))
        seg.analogsignals.append(asig)
        self.write_and_compare([block])

        anotherblock = Block("ir signal block")
        seg = Segment("ir signal seg")
        anotherblock.segments.append(seg)
        irsig = IrregularlySampledSignal(signal=np.random.random((20, 3)),
                                         times=self.rquant(20, pq.ms, True),
                                         units=pq.A)
        seg.irregularlysampledsignals.append(irsig)
        self.write_and_compare([block, anotherblock])

        block.segments[0].analogsignals.append(
            AnalogSignal(signal=[10.0, 1.0, 3.0],
                         units=pq.S,
                         sampling_period=pq.Quantity(3, "s"),
                         dtype=np.double,
                         name="signal42",
                         description="this is an analogsignal",
                         t_start=45 * pq.ms), )
        self.write_and_compare([block, anotherblock])

        block.segments[0].irregularlysampledsignals.append(
            IrregularlySampledSignal(times=np.random.random(10),
                                     signal=np.random.random((10, 3)),
                                     units="mV",
                                     time_units="s",
                                     dtype=np.float,
                                     name="some sort of signal",
                                     description="the signal is described"))
        self.write_and_compare([block, anotherblock])

    def test_signals_compound_units(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        units = pq.CompoundUnit("1/30000*V")
        srate = pq.Quantity(10, pq.CompoundUnit("1.0/10 * Hz"))
        asig = AnalogSignal(signal=self.rquant((10, 3), units),
                            sampling_rate=srate)
        seg.analogsignals.append(asig)

        self.write_and_compare([block])

        anotherblock = Block("ir signal block")
        seg = Segment("ir signal seg")
        anotherblock.segments.append(seg)
        irsig = IrregularlySampledSignal(signal=np.random.random((20, 3)),
                                         times=self.rquant(
                                             20, pq.CompoundUnit("0.1 * ms"),
                                             True),
                                         units=pq.CompoundUnit("10 * V / s"))
        seg.irregularlysampledsignals.append(irsig)
        self.write_and_compare([block, anotherblock])

        block.segments[0].analogsignals.append(
            AnalogSignal(signal=[10.0, 1.0, 3.0],
                         units=pq.S,
                         sampling_period=pq.Quantity(3, "s"),
                         dtype=np.double,
                         name="signal42",
                         description="this is an analogsignal",
                         t_start=45 * pq.CompoundUnit("3.14 * s")), )
        self.write_and_compare([block, anotherblock])

        times = self.rquant(10, pq.CompoundUnit("3 * year"), True)
        block.segments[0].irregularlysampledsignals.append(
            IrregularlySampledSignal(times=times,
                                     signal=np.random.random((10, 3)),
                                     units="mV",
                                     dtype=np.float,
                                     name="some sort of signal",
                                     description="the signal is described"))

        self.write_and_compare([block, anotherblock])

    def test_epoch_write(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        epoch = Epoch(times=[1, 1, 10, 3] * pq.ms,
                      durations=[3, 3, 3, 1] * pq.ms,
                      labels=np.array(["one", "two", "three", "four"]),
                      name="test epoch",
                      description="an epoch for testing")

        seg.epochs.append(epoch)
        self.write_and_compare([block])

    def test_event_write(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        event = Event(times=np.arange(0, 30, 10) * pq.s,
                      labels=np.array(["0", "1", "2"]),
                      name="event name",
                      description="event description")
        seg.events.append(event)
        self.write_and_compare([block])

    def test_spiketrain_write(self):
        block = Block()
        seg = Segment()
        block.segments.append(seg)

        spiketrain = SpikeTrain(times=[3, 4, 5] * pq.s,
                                t_stop=10.0,
                                name="spikes!",
                                description="sssssspikes")
        seg.spiketrains.append(spiketrain)
        self.write_and_compare([block])

        waveforms = self.rquant((3, 5, 10), pq.mV)
        spiketrain = SpikeTrain(times=[1, 1.1, 1.2] * pq.ms,
                                t_stop=1.5 * pq.s,
                                name="spikes with wf",
                                description="spikes for waveform test",
                                waveforms=waveforms)

        seg.spiketrains.append(spiketrain)
        self.write_and_compare([block])

        spiketrain.left_sweep = np.random.random(10) * pq.ms
        self.write_and_compare([block])

        spiketrain.left_sweep = pq.Quantity(-10, "ms")
        self.write_and_compare([block])

    def test_metadata_structure_write(self):
        neoblk = self.create_all_annotated()
        self.io.write_block(neoblk)
        blk = self.io.nix_file.blocks[0]

        blkmd = blk.metadata
        self.assertEqual(blk.name, blkmd.name)

        grp = blk.groups[0]  # segment
        self.assertIn(grp.name, blkmd.sections)

        grpmd = blkmd.sections[grp.name]
        for da in grp.data_arrays:  # signals
            name = ".".join(da.name.split(".")[:-1])
            self.assertIn(name, grpmd.sections)
        for mtag in grp.multi_tags:  # spiketrains, events, and epochs
            self.assertIn(mtag.name, grpmd.sections)

        srcchx = blk.sources[0]  # chx
        self.assertIn(srcchx.name, blkmd.sections)

        for srcunit in blk.sources:  # units
            self.assertIn(srcunit.name, blkmd.sections)

        self.write_and_compare([neoblk])

    def test_anonymous_objects_write(self):
        nblocks = 2
        nsegs = 2
        nanasig = 4
        nirrseg = 2
        nepochs = 3
        nevents = 4
        nspiketrains = 3
        nchx = 5
        nunits = 10

        times = self.rquant(1, pq.s)
        signal = self.rquant(1, pq.V)
        blocks = []
        for blkidx in range(nblocks):
            blk = Block()
            blocks.append(blk)
            for segidx in range(nsegs):
                seg = Segment()
                blk.segments.append(seg)
                for anaidx in range(nanasig):
                    seg.analogsignals.append(
                        AnalogSignal(signal=signal, sampling_rate=pq.Hz))
                for irridx in range(nirrseg):
                    seg.irregularlysampledsignals.append(
                        IrregularlySampledSignal(times=times,
                                                 signal=signal,
                                                 time_units=pq.s))
                for epidx in range(nepochs):
                    seg.epochs.append(Epoch(times=times, durations=times))
                for evidx in range(nevents):
                    seg.events.append(Event(times=times))
                for stidx in range(nspiketrains):
                    seg.spiketrains.append(
                        SpikeTrain(times=times,
                                   t_stop=times[-1] + pq.s,
                                   units=pq.s))
            for chidx in range(nchx):
                chx = ChannelIndex(name="chx{}".format(chidx),
                                   index=[1, 2],
                                   channel_ids=[11, 22])
                blk.channel_indexes.append(chx)
                for unidx in range(nunits):
                    unit = Unit()
                    chx.units.append(unit)
        self.writer.write_all_blocks(blocks)
        self.compare_blocks(blocks, self.reader.blocks)

    def test_multiref_write(self):
        blk = Block("blk1")
        signal = AnalogSignal(name="sig1",
                              signal=[0, 1, 2],
                              units="mV",
                              sampling_period=pq.Quantity(1, "ms"))
        othersignal = IrregularlySampledSignal(name="i1",
                                               signal=[0, 0, 0],
                                               units="mV",
                                               times=[1, 2, 3],
                                               time_units="ms")
        event = Event(name="Evee", times=[0.3, 0.42], units="year")
        epoch = Epoch(name="epoche",
                      times=[0.1, 0.2] * pq.min,
                      durations=[0.5, 0.5] * pq.min)
        st = SpikeTrain(name="the train of spikes",
                        times=[0.1, 0.2, 10.3],
                        t_stop=11,
                        units="us")

        for idx in range(3):
            segname = "seg" + str(idx)
            seg = Segment(segname)
            blk.segments.append(seg)
            seg.analogsignals.append(signal)
            seg.irregularlysampledsignals.append(othersignal)
            seg.events.append(event)
            seg.epochs.append(epoch)
            seg.spiketrains.append(st)

        chidx = ChannelIndex([10, 20, 29])
        seg = blk.segments[0]
        st = SpikeTrain(name="choochoo",
                        times=[10, 11, 80],
                        t_stop=1000,
                        units="s")
        seg.spiketrains.append(st)
        blk.channel_indexes.append(chidx)
        for idx in range(6):
            unit = Unit("unit" + str(idx))
            chidx.units.append(unit)
            unit.spiketrains.append(st)

        self.writer.write_block(blk)
        self.compare_blocks([blk], self.reader.blocks)

    def test_no_segment_write(self):
        # Tests storing AnalogSignal, IrregularlySampledSignal, and SpikeTrain
        # objects in the secondary (ChannelIndex) substructure without them
        # being attached to a Segment.
        blk = Block("segmentless block")
        signal = AnalogSignal(name="sig1",
                              signal=[0, 1, 2],
                              units="mV",
                              sampling_period=pq.Quantity(1, "ms"))
        othersignal = IrregularlySampledSignal(name="i1",
                                               signal=[0, 0, 0],
                                               units="mV",
                                               times=[1, 2, 3],
                                               time_units="ms")
        sta = SpikeTrain(name="the train of spikes",
                         times=[0.1, 0.2, 10.3],
                         t_stop=11,
                         units="us")
        stb = SpikeTrain(name="the train of spikes b",
                         times=[1.1, 2.2, 10.1],
                         t_stop=100,
                         units="ms")

        chidx = ChannelIndex([8, 13, 21])
        blk.channel_indexes.append(chidx)
        chidx.analogsignals.append(signal)
        chidx.irregularlysampledsignals.append(othersignal)

        unit = Unit()
        chidx.units.append(unit)
        unit.spiketrains.extend([sta, stb])
        self.writer.write_block(blk)

        self.compare_blocks([blk], self.reader.blocks)

        self.writer.close()
        reader = NixIO(self.filename, "ro")
        blk = reader.read_block(neoname="segmentless block")
        chx = blk.channel_indexes[0]
        self.assertEqual(len(chx.analogsignals), 1)
        self.assertEqual(len(chx.irregularlysampledsignals), 1)
        self.assertEqual(len(chx.units[0].spiketrains), 2)

    def test_to_value(self):
        section = self.io.nix_file.create_section("Metadata value test",
                                                  "Test")
        writeprop = self.io._write_property

        # quantity
        qvalue = pq.Quantity(10, "mV")
        writeprop(section, "qvalue", qvalue)
        self.assertEqual(section["qvalue"], 10)
        self.assertEqual(section.props["qvalue"].unit, "mV")

        # datetime
        dt = self.rdate()
        writeprop(section, "dt", dt)
        self.assertEqual(datetime.fromtimestamp(section["dt"]), dt)

        # string
        randstr = self.rsentence()
        writeprop(section, "randstr", randstr)
        self.assertEqual(section["randstr"], randstr)

        # bytes
        bytestring = b"bytestring"
        writeprop(section, "randbytes", bytestring)
        self.assertEqual(section["randbytes"], bytestring.decode())

        # iterables
        randlist = np.random.random(10).tolist()
        writeprop(section, "randlist", randlist)
        self.assertEqual(randlist, section["randlist"])

        randarray = np.random.random(10)
        writeprop(section, "randarray", randarray)
        np.testing.assert_almost_equal(randarray, section["randarray"])

        # numpy item
        npval = np.float64(2398)
        writeprop(section, "npval", npval)
        self.assertEqual(npval, section["npval"])

        # number
        val = 42
        writeprop(section, "val", val)
        self.assertEqual(val, section["val"])

        # empty string
        writeprop(section, "emptystring", "")
        self.assertEqual("", section["emptystring"])

    def test_annotations_special_cases(self):
        # Special cases for annotations: empty list, list of strings,
        # multidimensional lists/arrays
        # These are handled differently on read, so we test them on a block
        # instead of just checking the property writer method
        # empty value

        # empty list
        wblock = Block("block with empty list", an_empty_list=list())
        self.writer.write_block(wblock)
        rblock = self.writer.read_block(neoname="block with empty list")
        self.assertEqual(rblock.annotations["an_empty_list"], list())

        # empty tuple (gets read out as list)
        wblock = Block("block with empty tuple", an_empty_tuple=tuple())
        self.writer.write_block(wblock)
        rblock = self.writer.read_block(neoname="block with empty tuple")
        self.assertEqual(rblock.annotations["an_empty_tuple"], list())

        # list of strings
        losval = ["one", "two", "one million"]
        wblock = Block("block with list of strings", los=losval)
        self.writer.write_block(wblock)
        rblock = self.writer.read_block(neoname="block with list of strings")
        self.assertEqual(rblock.annotations["los"], losval)