Skip to content
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

Add NeuronexusRawIO/IO #1509

Merged
merged 20 commits into from
Sep 27, 2024
Merged

Add NeuronexusRawIO/IO #1509

merged 20 commits into from
Sep 27, 2024

Conversation

zm711
Copy link
Contributor

@zm711 zm711 commented Jul 18, 2024

Fixes #1296.

I'll try to work on this a bit in my free time. Will switch off draft when ready for review.

Also should help for neuroconv

  • Add tests
  • Get file on GIN

@zm711 zm711 changed the title Add a NeuronexusRawIO Add NeuronexusRawIO/IO Jul 18, 2024
@zm711 zm711 marked this pull request as ready for review July 24, 2024 16:19
@zm711 zm711 requested a review from apdavison July 24, 2024 16:20
@zm711
Copy link
Contributor Author

zm711 commented Jul 24, 2024

No rush on this @apdavison, this is a new io. Since Sam will be going on vacation, I think getting some feedback would be nice, but I can also pester him once he is back. There is no rush on this one :)

neo/rawio/neuronexusrawio.py Outdated Show resolved Hide resolved
@apdavison apdavison added this to the 0.14.0 milestone Jul 26, 2024
Copy link
Contributor

@h-mayorquin h-mayorquin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, can I approve things? How comes? Just testing.

Did the first reading, this looks pretty good to me. A bunch of minor comments.

neo/rawio/neuronexusrawio.py Outdated Show resolved Hide resolved
neo/rawio/neuronexusrawio.py Show resolved Hide resolved
neo/rawio/neuronexusrawio.py Outdated Show resolved Hide resolved
neo/rawio/neuronexusrawio.py Show resolved Hide resolved
neo/rawio/neuronexusrawio.py Show resolved Hide resolved
neo/rawio/neuronexusrawio.py Outdated Show resolved Hide resolved
neo/rawio/neuronexusrawio.py Outdated Show resolved Hide resolved
neo/test/iotest/test_neuronexusio.py Show resolved Hide resolved
#######################################
# Helper Functions

def read_metadata(self, fname_metadata):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like to add path (hungarian notation) to differentiate between file handles (output of f = open() and paths) but I think name works as well!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the parsing is super fast, but one thing I was thinking of was we could allow think about parsing more of header in this function then in spikeinterface or in neuroconv stuff you could run this function separately if you needed separate metadata then we could add a check in the main body that if this is already run we don't need to re-run. But the thought was inchoate (because honestly this function is so small right now). Maybe next time we have a call we can brainstorm on this because I don't think I'm explaining myself super well.

As far as naming, I just didn't want to use the same name so I added the fname tag onto it. But happy to change if it helps in conceptualizing more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might be a good idea, I wish I knew more of the metadata to help you decide there.

Concerning the naming, it was just a random comment about what I do. I was saying that adding name makes sense as well!

neo/rawio/neuronexusrawio.py Show resolved Hide resolved
@h-mayorquin
Copy link
Contributor

To discuss here: expose logical streams instead of buffer streams for this format.

@zm711
Copy link
Contributor Author

zm711 commented Aug 23, 2024

It would be relatively easy. My only concern is that if we have a universal way to do this then we are adding more work to adapt all of these rawios into the new format. But in this case the last six channels are reserved for the non-ephys data. So I could split these off intro logical streams.

@zm711
Copy link
Contributor Author

zm711 commented Aug 27, 2024

Or we could merge this as is and then iterate for the logical streams in a new PR. That way if the buffer -> stream api happens before we have time then we fold that in and if this becomes an issue for users we can quickly fix it upon request before the api is added.

@zm711
Copy link
Contributor Author

zm711 commented Aug 27, 2024

@samuelgarcia, this one can also take a review in your queue. Just pinging you now that you're back here. We have a couple requests on spikeinterface (and on neuroconv) for this. At your leisure of course.

@zm711 zm711 requested review from samuelgarcia and alejoe91 and removed request for apdavison September 13, 2024 14:03
@zm711
Copy link
Contributor Author

zm711 commented Sep 16, 2024

C'est le ping à Sam de la semaine.

@h-mayorquin
Copy link
Contributor

ceci n'est pas une ping

@zm711
Copy link
Contributor Author

zm711 commented Sep 16, 2024

He's on the thread. He'll see it :P

self.header["event_channels"] = event_channels

# Add the minimum annotations
self._generate_minimal_annotations()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance to have a rec_datetime in the metadata dict ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember. Let me check!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay so I'm adding to the header like this:

self.header['rec_datetime'] = self.metadata['status']['start_time']

It is setup like: date and time. Do you want any other info?

@samuelgarcia
Copy link
Contributor

Salut Zach.
This looks good to me.
I made one or two comments.
Sorry for the long delay.

zm711 and others added 2 commits September 23, 2024 10:39
Co-authored-by: Garcia Samuel <sam.garcia.die@gmail.com>
@zm711
Copy link
Contributor Author

zm711 commented Sep 23, 2024

Thanks Sam. I think this is ready to go now after your feedback!

# Add the minimum annotations
self._generate_minimal_annotations()

self.header['rec_datetime'] = self.metadata['status']['start_time']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zm711 could check this instead ?
the rec_datetime must be a real datatime and this must routed inside raw_annotaion at block and segment level for instance like this

Suggested change
self.header['rec_datetime'] = self.metadata['status']['start_time']
rec_datetime = datetime.datetime(self.metadata['status']['start_time'])
bl_annotations = self.raw_annotations["blocks"][0]
seg_annotations = bl_annotations["segments"][0]
for d in (bl_annotations, seg_annotations):
d["rec_datetime"] = rec_datetime

Comment on lines 222 to 241
# date comes out as:
# year-month-daydayofweektime all as a string so we need to prep it for
# entering into datetime
# example: '2024-07-01T13:04:49.4972245-04:00'
stringified_date_list = self.metadata['status']['start_time'].split('-')
year = int(stringified_date_list[0])
month = int(stringified_date_list[1])
day = int(stringified_date_list[2][:2]) # day should be first two digits of the third item in list
time_info = stringified_date_list[2].split(':')
hour = int(time_info[0][-2:])
minute = int(time_info[1])
second = int(time_info[2])
microsecond = 1000 * 1000 * (float(time_info[2]) - second) # second -> micro is 1000 * 1000

rec_datetime = datetime.datetime(year, month, day, hour, minute, second, microsecond)
bl_annotations = self.raw_annotations["blocks"][0]
seg_annotations = bl_annotations["segments"][0]
for d in (bl_annotations, seg_annotations):
d["rec_datetime"] = rec_datetime

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@samuelgarcia so I don't do as much date time stuff you want to look at this. Basically we get this string. I don't know what "T" inside the string or the 4:00 at the end (maybe duration in seconds?) so I did some ugly parsing. If you have a better idea from the parsing let me know!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess my fear with this type of parsing is that if they change how they encode it we end up with giant parsing logic.

Copy link
Contributor

@h-mayorquin h-mayorquin Sep 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2024-07-01T13:04:49.4972245-04:00
date_time_{T}_{timestamp}_{time_zone}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@h-mayorquin if you have a good system could you actually make a PR off of this one and I'll merge it into this. I'm trash at this parsing and it seems like you have a better idea of how to pull this out!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are ready to merge this @h-mayorquin unless you have a better idea for parsing. Do you want me to hold off until you take a look or good to merge and we can prettify this bit later?

@samuelgarcia
Copy link
Contributor

merci

@samuelgarcia samuelgarcia merged commit 375c973 into NeuralEnsemble:master Sep 27, 2024
3 checks passed
@zm711 zm711 modified the milestones: 0.14.0, 0.13.4 Oct 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for Neuronexus (.XDAT) files
4 participants