-
Notifications
You must be signed in to change notification settings - Fork 261
Adding MED format, second submission #1241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @dancrepeau!
Thanks for rewriting the IO! I think the segment & stream concept is not implemented consistently yet. I left some comments in the code. Tell me if you need more details on this. I think a test file with more than one segment (by design or discontinuous data) would be beneficial here to implement this. Based on the tests you wrote I guess the current test file is a single segment only, right?
neo/io/__init__.py
Outdated
from neo.io.klustakwikio import KlustaKwikIO | ||
from neo.io.kwikio import KwikIO | ||
from neo.io.mearecio import MEArecIO | ||
from neo.io.medio import MedIO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is nitpicking, but this change should be one line further down to be in alphabetical order....
neo/rawio/medrawio.py
Outdated
for seg_idx in range(self._nb_segment): | ||
for template in self._stream_templates: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are creating one stream
per segment and stream template. However, streams are shared between all segments. I think you are generating more streams than required and could just use the stream_templates as streams. Or is this a feature of MED that in each segment you could have different streams
and channels
?
neo/rawio/medrawio.py
Outdated
spike_channels = np.array(spike_channels, dtype=_spike_channel_dtype) | ||
|
||
# Events | ||
# events are not being read by this Neo wrapper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have implemented methods below to read event data, so you should also create the corresponding event header for those methods to be used.
neo/rawio/medrawio.py
Outdated
seg_ann = bl_ann['segments'][0] | ||
seg_ann['name'] = 'Seg #0 Block #0' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are implementing a multi-segment IO, so it would make sense provide a (less generic) name for all segments.
neo/test/iotest/test_medio.py
Outdated
for ana in seg.analogsignals: | ||
assert isinstance(ana, AnalogSignalProxy) | ||
ana = ana.load() | ||
assert isinstance(ana, AnalogSignal) | ||
for st in seg.spiketrains: | ||
assert isinstance(st, SpikeTrainProxy) | ||
st = st.load() | ||
assert isinstance(st, SpikeTrain) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are testing basic RawIO functionality here. This should be already covered in other tests in Neo, so I would not duplicate it here.
neo/test/iotest/test_medio.py
Outdated
|
||
seg = r.read_segment(lazy=False) | ||
|
||
# There will only be one analogsignals in a MED reading |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# There will only be one analogsignals in a MED reading | |
# There will only be one analogsignal in a MED reading |
neo/test/iotest/test_medio.py
Outdated
bl = r.read_block(lazy=True) | ||
self.assertTrue(bl.annotations) | ||
|
||
seg = bl.segments[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depending on your test file the IO should generate more than 1 segment. If there's more segments, could you also check those?
neo/test/iotest/test_medio.py
Outdated
self.assertNotEqual(st.size, 0) | ||
|
||
# annotations | ||
#assert 'seg_extra_info' in seg.annotations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You added MED specific annotations to the block. You could confirm that these are correctly annotated on the block level. (in test_read_block
)
Hi @JuliaSprenger! Thank you for reviewing the code. I will go through your comments thoroughly in the coming days. I will comment right away that we are indeed testing against a recording that has discontinuous ranges, specifically "test.medd". Starting on line 76 of test_medrawio.py, we are verifying that it found 3 segments, and there are two unique streams in each segment (6 streams total). If streams are supposed to be shared across all segments, then I will have to re-work the code. I'm using the convention that a continuous stretch of data is a segment, and within that, a stream is a grouping of channels that have the same sampling frequency. Please correct me if I have those ideas wrong. My notion of a "template" (which admittedly isn't clear) is just a grouping of channels that have the same sampling frequency. However, there can be lots of discontinuitites within a recording, so I am multiplying the templates by continuous ranges, and assuming those are streams. I am assuming a stream can't have gaps in it. Thanks again for all the help! |
Hi @dancrepeau, In the RawIO design a stream is independently of segments describing different I hope that helps restructuring, let me know if you are still missing some information. |
Hi @JuliaSprenger, Thank you for the clarifications. The terminology here can become very confusing. In MED, segments and continuous sections are independent concepts, as segments are primarily used to break recordings up into smaller files, but can also be used to indicate a new experiment within a recording. I might suggest some changes to documentation to make these Neo concepts easier for newcomers to digest (and feel free to disregard me here, as I am jus trying to be helpful). The Neo core documentation (https://neo.readthedocs.io/en/stable/core.html) only shows a higher level view; indeed the word "stream" doesn't appear anywhere on this page. I found the file "baserawio.py" to be helpful in understanding the raw io concepts, however I came to some wrong conclusions. For example, the function: def get_signal_t_start(self, block_index, seg_index, stream_index=None): Again, I appreciate the clarifications! |
Hello,
A month or so ago, my colleague Matt Stead and I pushed a fork with changes to support the MED format (medformat.org). This new pull request is for a version that's a bit more detailed: it finds discontinuities and creates separate Neo segments, and it groups channels together that have the same sampling frequencies. It also reads Note and Neuralynx type annotations, and has two time basis options, zero-based and original time.
Please let me know if there are questions/comments/criticisms! Thank you,
Dan