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

Work on image-display user experience #217

Merged
merged 4 commits into from
Jun 6, 2019
Merged

Conversation

pkgw
Copy link
Contributor

@pkgw pkgw commented Jun 5, 2019

(This PR is cumulative on #216)

The main goal here is to add controls to the Jupyter widget so that the user can interactively tune the image stretch parameters straight in their notebook.

Screenshot from 2019-06-05 14-34-46

I set this up so that the Qt version of the widget should be unaffected.

I also ran into some issues with hidden JupyterLab widget views that look pretty thorny; I have some lengthy commit messages describing what I found and a workaround I put into place.

pkgw added 4 commits June 6, 2019 10:48
In the Jupyter widget system, it is possible to create multiple views of a
single widget model. Views can be "detached", in which case their underlying
DOM elements are removed from the document. This is what happens if you create
a WWT view in a JupyterLab notebook, use the "Create a new view for this
output" context menu item to move the output to a new tab, and then hide the
original output. There is one underlying widget model and two views, only one
of which has active DOM elements.

The wrinkle for pywwt is that all of our widget state is stored inside the
<iframe> that does the rendering, so we're not really a real model-view setup.
The way things currently work, operations that affect the widget state are
passed as message from Python to JS, which are then distributed to all of the
views. So long as all views receive the same messages, things should stay in
sync. (Although if you create a widget, do some things to it, and then create
a new view of it, that view will have missed historical messages and so will
be out of sync.)

The problem I discovered was that if you send messages to a "detached" widget
view, you sometimes get JS exceptions. And apparently the code that
distributes the messages just terminates, preventing the control messages from
being sent to other widget views. This means that those views basically stop
responding to any Python controls.

This is bad news for the workflow of creating a WWT view then moving it to a
separate tab, which is something we very much want to support for UX reasons.
The real solution is to Do The Right Thing when a widget is detached, so that
the JS exceptions don't happen in the first place, but that's going to take
some time to get right. In the meantime, let's just log and swallow those JS
exceptions, so that the message passing can keep on working to the views that
aren't broken. This will keep things limping along.
… are applied

The way that the ImageLayer constructor was structured, any user specification
of the vmax and vmin values would be overridden. Restructure to prefer them,
and also make sure that the settings are applied but not in a redundant way.
…class

This custom subclass exposes some work-in-progress controls that allow the
image display parameters to be adjusted interactively.
Now by showing `my_image_layer.controls` you get widgets that let you adjust
the opacity, stretch function, and data range. The best UI I could come up
with for the data range has "coarse" controls that are typed in manually and
"fine" controls that use a range slider widget.

I note that in my testing, the adjustments don't apply until focus changes to
another widget, which makes for a kind of weak UX. I checked the ipywidgets
bug tracker but don't see any complaints about this; I'm not sure what's going
on, since this seems like a pretty basic piece of functionality.
@codecov
Copy link

codecov bot commented Jun 6, 2019

Codecov Report

Merging #217 into master will decrease coverage by 0.89%.
The diff coverage is 25.64%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master     #217     +/-   ##
=========================================
- Coverage   57.81%   56.91%   -0.9%     
=========================================
  Files          24       24             
  Lines        1695     1727     +32     
=========================================
+ Hits          980      983      +3     
- Misses        715      744     +29
Impacted Files Coverage Δ
pywwt/jupyter.py 0% <0%> (ø) ⬆️
pywwt/layers.py 89.62% <100%> (ø) ⬆️
pywwt/core.py 70.21% <100%> (+0.48%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ba1b28a...ac8b919. Read the comment docs.

@pkgw
Copy link
Contributor Author

pkgw commented Jun 6, 2019

This needs docs, but I'm going to merge now. (I'm also going to ignore the minor hit in code coverage.) I want to rearrange the docs a bit anyway, so that will wait til another pull request.

@pkgw pkgw merged commit 359cc0f into WorldWideTelescope:master Jun 6, 2019
@pkgw pkgw deleted the image-ux branch June 6, 2019 20:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant