-
Notifications
You must be signed in to change notification settings - Fork 74
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
Sonify plugin updates #3269
base: main
Are you sure you want to change the base?
Sonify plugin updates #3269
Conversation
Sonify plugin updates jt
…ch for now, while awaitin PyPI release
Some more functionality tweaks
57ee976
to
cc51183
Compare
Looks good! A couple of questions:
|
The released version of strauss does not include all the fixes to get it working with Jdaviz so instead we use "strauss@git+https://github.com/james-trayford/strauss@equal_loudness_normalisation" in the
Good call!
I'm not sure I see what you mean. When testing with model fitting, I see the spinner in the same location as the Sonify Data button. |
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.
is it possible to keep any of this logic in the plugin itself? It's very specific to this single plugin (right now - maybe eventually we'll have more generic audio support). Right now, if I understand correctly, there is a limitation of a single sonified cube at a time (running sonify replaces any previous instances), so I don't see much benefit to having this be specifically per-viewer logic.
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 audio stream needs to be connected to the viewer (at least with the current implementation) so that certain mouse events can turn the stream on or off. The audified cube needs to 'live' somewhere and right now the viewer is the best place for that. Once we decouple the sonified cube from the spectrum-at-spaxel tool and have it as a separate data object, this should be doable. I will create a follow-up ticket and include that context.
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.
we can connect the event handling to the tool/viewer but still keep all the logic in the plugin (I think). Its just nice to keep all the code in one place and not "pollute" the viewer code with logic that only applies to one plugin (which is intended to be modular).
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.
try: | ||
from strauss.sonification import Sonification | ||
from strauss.sources import Events | ||
from strauss.score import Score | ||
from strauss.generator import Spectralizer | ||
from tqdm import tqdm | ||
except ImportError: | ||
pass |
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.
is it possible for any of these imports to fail but there still be a call to any of the logic below (either manual API calls or if none of the imports in the plugin itself fail and so _has_strauss = True
but tqdm
failed to import, for example)?
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.
None of the methods are public API and tqdm
is a dependency of Strauss, but I can see that being an issue down the road. Is it alright for this to be a follow-up?
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 wonder if we can either put the import tqdm
in the else
or import _has_strauss
from the plugin. But yes, probably can be a follow-up.
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 think if we decide to move most of the cube_listener.py
code to the sonify plugin then we can include this effort in #3330 .
sys.stderr = old_stderr | ||
|
||
|
||
def audify_spectrum(spec, duration, overlap=0.05, system='mono', srate=44100, fmin=40, fmax=1300, |
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 whole function is never reached by tests - is it possible to add coverage (or if out of scope, can we create a follow-up)?
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.
on closer look, it seems that the existing tests added in this PR are probably never actually running on CI because of dependencies. Can we add strauss to at least one of the runners so they do run?
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.
Can I add the Strauss package to all
in pyproject.toml
or should I create a new workflow for Strauss?
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.
let's discuss - it might be time to make a convention for this and do the same thing for footprints, Roman, and strauss.
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.
any resolution to the test coverage situation?
return soni.loop_channels['0'].values | ||
|
||
|
||
class CubeListenerData: |
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.
same as above re test coverage
:uses_active_status="uses_active_status" | ||
@plugin-ping="plugin_ping($event)" | ||
:keep_active.sync="keep_active" |
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.
instead of using the spectrum at spaxel tool, we could have the mouseover events enabled whenever the plugin is active 🤔 (could be a follow-up, especially given the conversation about potential future audio layers)
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.
Yes, follow-up effort tracked at #3331
<v-alert v-if="!has_strauss" type="warning" style="margin-left: -12px; margin-right: -12px"> | ||
To use Sonify Data, install strauss and restart Jdaviz. You can do this by running `pip install .[strauss]` | ||
in the command line and then launching Jdaviz. | ||
</v-alert> |
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.
can use the disabled_msg
traitlet instead and then the rest of the plugin will automatically not be shown without having to v-else
everything else.
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.
We would lose the yellow alert box but that's fine with me.
@@ -134,6 +137,8 @@ filterwarnings = [ | |||
"ignore:The unit 'Angstrom' has been deprecated in the VOUnit standard\\. Suggested.* 0\\.1nm\\.", | |||
"ignore:((.|\n)*)Sentinel is not a public part of the traitlets API((.|\n)*)", | |||
"ignore:datetime\\.datetime\\.utcfromtimestamp:DeprecationWarning", # asdf + dateutil<=2.8.2 + Python 3.12 | |||
"ignore:'audioop' is deprecated and slated for removal in Python 3.13", |
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.
do we need a follow-up to address this before 3.13 comes out? What should be used instead?
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 an upstream issue, I can make a note of these warnings and pass them along to the Strauss team.
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.
Follow-up for tracking that information #3332
@@ -134,6 +137,8 @@ filterwarnings = [ | |||
"ignore:The unit 'Angstrom' has been deprecated in the VOUnit standard\\. Suggested.* 0\\.1nm\\.", | |||
"ignore:((.|\n)*)Sentinel is not a public part of the traitlets API((.|\n)*)", | |||
"ignore:datetime\\.datetime\\.utcfromtimestamp:DeprecationWarning", # asdf + dateutil<=2.8.2 + Python 3.12 | |||
"ignore:'audioop' is deprecated and slated for removal in Python 3.13", | |||
"ignore:Importing display from IPython.core.display is deprecated since IPython 7.14, please import from IPython.display", |
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.
where does this need to be fixed? Is there an upstream issue?
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.
Same as above.
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.
self.cursig[:] = self.sigcube[self.idx1, self.idx2, :] | ||
self.newsig[:] = self.cursig[:] | ||
t1 = time.time() | ||
print(f"Took {t1-t0}s to process {self.cube.shape[0]*self.cube.shape[1]} spaxels") |
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.
is this print statement a temporary way to inform the user or for debugging?
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 think it was originally for debugging but now it might be useful for logging performance. cube_listener.py
is pretty isolated right now but maybe it could be a snackbar message once we figure out where this code should live.
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 left a couple minor comments, I think given the follow up tickets that already exist (and the additional one I suggested) I'd be ok merging this. I'm going to sit on it until tomorrow morning and let my thoughts stew before I approve.
for i in tqdm(range(self.cube.shape[0])): | ||
for j in range(self.cube.shape[1]): |
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.
Any time I see nested for loops it makes me twitch - I forget how long this takes, but I would advocate for a follow-up ticket to multiprocess
this (given that it doesn't seem amenable to vectorization) like we do for cube model fitting.
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.
Good call, tracking that issue at #3339 .
wsrt = np.sort([w1, w2]) | ||
self.wl_bounds = tuple(wsrt) | ||
|
||
def audify_cube(self): |
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.
Given that audify_spectrum
is outside the class as an independent function, and this pretty much just uses self.cube
from self
, I wonder if this could/should be pulled out into a function that takes cube
as input and returns what's needed to the class 🤔. Probably not important, it just seemed a little wonky to have audify_spectrum
outside this class and this inside. Maybe it's just that audify_spectrum
would be better off in the sonify plugin file.
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 think that is what #3330 is hoping to fix by moving some/all of the cube_listener.py
code into the sonify data plugin.
Co-authored-by: Ricky O'Steen <[email protected]>
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.
Still needs a changelog entry, but I'm approving assuming you'll add that before merging.
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 hard to test because standalone jobs are all currently failing on main
.
@@ -82,6 +82,9 @@ docs = [ | |||
roman = [ | |||
"roman_datamodels>=0.17.1", | |||
] | |||
strauss = [ | |||
"strauss@git+https://github.com/james-trayford/strauss@equal_loudness_normalisation" |
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.
PyPI won't take this. Strauss needs a stable release or you can only install it in tox.ini
. But if the latter, Jdaviz better still be able to run if strauss is not installed.
I think you also introduced a dependence to tqdm
but it is not declared here.
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.
Ok I reached out to James from the Strauss team to see if we can get a release of Strauss out soon. Should I add tqdm
to our dependencies if it only is used for Strauss?
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 should add it under the strauss
directive here, no? I see you explicitly trying to import it in cube_listener.py
.
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.
p.s. Do we really need it? Isn't it for command line progress bar? But we are a GUI program here, not TUI.
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's something else I can bring up with the Strauss team.
In terms of CI, you can set something up like this for Roman:
Then we can slap "Extra CI" label on this PR. |
Description
This pull request takes the work from james-trayford#3 and moves it into a PR for Jdaviz. There is now a plugin called "Sonify Data" which contains configuration options for sonifying a data cube. There are also options for which speaker the sound will come from, volume, and to start/stop the stream so the spectrum-at-spaxel tool can work as usual after sonifying the cube.
Change log entry
CHANGES.rst
? If you want to avoid merge conflicts,list the proposed change log here for review and add to
CHANGES.rst
before merge. If no, maintainershould add a
no-changelog-entry-needed
label.Checklist for package maintainer(s)
This checklist is meant to remind the package maintainer(s) who will review this pull request of some common things to look for. This list is not exhaustive.
trivial
label.