raphaelvallat / yasa

YASA (Yet Another Spindle Algorithm): a Python package to analyze polysomnographic sleep recordings.
https://raphaelvallat.com/yasa/
BSD 3-Clause "New" or "Revised" License
428 stars 115 forks source link

Add Hypnogram.plot_hypnogram method #122

Closed remrama closed 1 year ago

remrama commented 1 year ago

I'm finalizing a PR that will bring yasa.plot_hypnogram up to speed with the new yasa.Hypnogram class (#116).

I'm only opening this Issue because I'm looking for some feedback before finalizing the PR: Currently, I have yasa.plot_hypnogram requiring a yasa.Hypnogram as input. All the attributes make it way easier to handle all the plotting. Should it also allow a sequence as it used to? Maybe with deprecation warning? I suppose this a bigger-picture question of how all the updated functions should work in v0.7.0. If it requires a yasa.Hypnogram instance, then maybe all examples should just use the method rather than taking the Hypnogram as input?

After addressing this, I'll submit the PR after #121 is merged into master to avoid potential conflicts.

raphaelvallat commented 1 year ago

Awesome looking forward to it! I'll finish reviewing the other PR today or tomorrow.

So, for plot_hypnogram, I would just go full-on with the new Hypnogram class. This will greatly simplify the code, and this function was introduced recently so I think it's okay to make API-breaking changes. In other words, using an array_like input is not allowed anymore.

For newly-introduced Hypnogram methods (sleep_statistics, transition_matrix, find_periods)

For yasa.SleepStaging

For all other functions (events detection, spectral)

Curious to hear your thoughts on the above.

raphaelvallat commented 1 year ago

For plot_hypnogram, you can also do what I did for sleep_statistics, i.e. duplicate the code for the Hypnogram method and keep the original implementation intact. If doing that, then we should add a DeprecationWarning to the original implementation, and in the future remove it from the public API, as with all other hypnogram-related functions. Your preference will be mine!

remrama commented 1 year ago

Awesome, this all sounds good. I was hoping we could ditch the array input! 👍

For plot_hypnogram, you can also [...] duplicate the code for the Hypnogram method and keep the original implementation intact.

I've already taken the approach of changing the original implementation, but lmk if you want me to switch back. Currently, the original function takes a Hypnogram object as input, and then the method is just a one line of return plot_hypnogram(self, **kwargs). I prefer this because it keeps the plotting libraries isolated and also avoids being pretty invasive on the yasa.Hypnogram source code. I think a full transfer from function to method would disproportionately invade that file, especially if other plotting variants/options get added in the future.

But one thing about this: I have a few examples that looks like plot_hypnogram(hyp, ...) and others like hyp.plot_hypnogam(...). Both work for now, but I'm wondering if I should only show examples that use the Hypnogram method to avoid confusion?

raphaelvallat commented 1 year ago

I would suggest going ahead with returning a Hypnogram object from yasa.SleepStaging in v0.7

You're right — let's do it!

Regarding the other functions (detections), I think for now let's not change the input. We will require the users to manually use the Hypnogram.upsample_to_data method, which is close to what they're already doing anyway. I have been considering that maybe we can take care of the upsampling internally such that the users would just pass spindles_detect(hypno=<yasa.Hypnogram at 30-seconds> , include=["N2", "N3"]). But at the same time I kinda like that the users are responsible for the upsampling.

👍 on your approach for plot_hypnogram.

only show examples that use the Hypnogram method to avoid confusion?

Yup!

remrama commented 1 year ago

But at the same time I kinda like that the users are responsible for the upsampling.

Ha yes I hadn't thought about this... that the power of the Hypnogram object is so strong that it might risk a dangerous disconnect between the user and the underlying analysis! Good to be aware of and I like your idea of keeping some steps in.

raphaelvallat commented 1 year ago

the power of the Hypnogram object is so strong

This will be the first line in the new release changelog 😂