-
Notifications
You must be signed in to change notification settings - Fork 223
Add to_pynapple_tsgroup
function
#4074
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 to_pynapple_tsgroup
function
#4074
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.
Two initial comments and then lets see about the tests passing :)
elif isinstance(sorting_analyzer_or_sorting, BaseSorting): | ||
sorting = sorting_analyzer_or_sorting | ||
else: | ||
raise TypeError("The function `to_pynapple_tsgroup` only accepts a SortingAnalyzer or Sorting object.") |
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.
Could we return the type of the object that was accidentally given. For me I sometimes confuse the order of rec, sorting in generate_ground_truth_recording so it would be nice to know I put in a recording instead of a sorting/analyzer.
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.
I had a go, what do you think of the new message?
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.
Sorry never responded. This is great Thanks!
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.
Forgot to do the docs really quick :)
|
||
def to_pynapple_tsgroup( | ||
sorting_analyzer_or_sorting: SortingAnalyzer | BaseSorting, | ||
metadata: pd.DataFrame | dict | None = None, |
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.
Also what if we let the user choose a list of metadata and then we organize it instead. Right? each unit could have location + qm + tm all in one big dataframe for Pynapple?
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.
I don't understand. Like, they specify "unit_locations", "quality_metrics", etc?
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.
I missed what you were doing. I see it now. Maybe that is a little too complicated. If they wanted to do the dataframe on their own could they add metadata to the pynapple structure later. Basically if they want to use the export correctly they have to put a None in for this argument. So doing a dict or dataframe is just hijacking it.
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.
Yeah, there is a set_info
method for the TsGroup. So we could ignore the metadata, and get the user to attach it after creation. Maybe we can discuss at the next meeting
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.
That sounds good. I don't think this comment style is letting my point come across clearly.
I like the idea of exporting metadata, but I don't like the idea of letting the user do a million different styles of metadata. I would prefer them to give a list of spikeinterface metadata they want that we could export for them. If they just want to set their own metadata then I don't think this function is for that so I think the finer point there is better to talk about then write about.
Although fair this complicates the definition of |
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.
Few more typos found. I still wonder about the metadata bit. But definitely better to just discuss in person.
Hello, I met with the Pynapple team (@gviejo, @sjvenditto, @wulfdewolf) at FlatIron. We loosely talked about the PR, with two main discussion points:
|
Co-authored-by: Zach McKenzie <[email protected]>
I support the selecting
I support this. My point here is I think it should either be a bool (export all possible spikeinterface stuff or export nothing) or a list of things you want to export (quality metrics, template metrics, etc). I just don't think we should allow the user to feed in an arbitrary dataframe that we will then export for them. So based on what the pynapple team is saying (hi to all of you!) I would make it an export bool. |
This could be cool to have this for the relase no ? And we can improve a bit later. |
Ahhh, ok, got you! So if bool=False, the user should make the TsGroup, then add their own metadata to that using pynapple functionality? I like that! |
not for this PR, but if we are pursing this strategy in general we should add a note in the documentation that we would support export layers for projects that want to create their own export specific code. Might be worth discussion at the maintenance meeting just like we have a section in the sorter section explaining how to get your sorter added to the code base. |
Done dirty by hugging face :P |
pyproject.toml
Outdated
@@ -141,6 +141,7 @@ test_extractors = [ | |||
# Commenting out for release | |||
"probeinterface @ git+https://github.com/SpikeInterface/probeinterface.git", | |||
"neo @ git+https://github.com/NeuralEnsemble/python-neo.git", | |||
"pynapple", |
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.
REMOVE!!!
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.
1 typo
1 ? style
2 questions regarding the int try-except
|
||
unit_ids_castable = True | ||
try: | ||
unit_ids_ints = [int(unit_id) for unit_id in unit_ids] |
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.
Another strategy that wouldn't use the try-except would be
unit_ids_castable = all([unit_id.isdigit() for unit_id in unit_ids])
if unit_ids_castable:
unit_ids_ints = [int(unit_id) for unit_id in unit_ids]
else:
xx
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.
Never mind. This only works if the ids are string. --which maybe in the future they will be ;P
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.
Yeah, I thought about this too and ended up try/excepting.
all([isinstance(unit_id, int) or unit_id.isdigit() for unit_id in unit_ids])
works but is a bit gross.
I'd vote to keep the try/except for now
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.
The costs are minimal, but based on my reading a try-except is slightly faster than an if-else if you succeed most of the time, but is quite a bit slower if you except often. That being said even a 10x slowdown of one step isn't really that meaningful. so now that you added in the specific except I'm okay with this. Thanks for humoring me :)
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.
After putting you through the ringer this is good by me. :)
🙌 🎉 |
Adds the ability to export a SortingAnalyzer or Sorting to a TsdGroup object from pynapple (https://pynapple.org/user_guide/01_introduction_to_pynapple.html#nap-tsgroup-group-of-timestamps). Made with advice from @gviejo, at NeuroDataReHack 2025!
Tests and docs included.
Some comments:
return_times
argument inget_unit_spike_train
. This can be a bit confusing for the user - what happens with multi-segments etc? We really need to finish our time doc!!