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 interactive masking tool #521

Merged
merged 22 commits into from
Jun 11, 2024
Merged

Add interactive masking tool #521

merged 22 commits into from
Jun 11, 2024

Conversation

nvaytet
Copy link
Member

@nvaytet nvaytet commented Jun 3, 2024

This is scipp/essreduce#30 moved to Scippneutron.

Part of scipp/essdiffraction#50

  • Masks can be drawn on 1d and 2d data (using mpltoolbox).
  • They can then be saved to file, using Scipp's hdf5 format.
  • Only rectangular and horizontal/vertical spans are supported for now.

Screenshot at 2024-05-24 00-06-34
Screenshot at 2024-05-24 00-05-51

@nvaytet nvaytet marked this pull request as draft June 3, 2024 13:41
@nvaytet nvaytet marked this pull request as ready for review June 4, 2024 21:13
@jl-wynen jl-wynen self-assigned this Jun 7, 2024
Copy link
Member

@jl-wynen jl-wynen left a comment

Choose a reason for hiding this comment

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

I have a lot of comments but they are mostly about small issues. It looks good overall!

@@ -87,6 +88,7 @@ filterwarnings = [
'ignore:Widget.widget_types is deprecated:DeprecationWarning',
'ignore:Widget.widgets is deprecated:DeprecationWarning',
'ignore:`load_nexus` is deprecated:UserWarning',
'ignore:Passing unrecognized arguments to super:DeprecationWarning',
Copy link
Member

Choose a reason for hiding this comment

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

Where does this come from?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is also in Plopp. The warning pops up when using ipympl. I was never able to fix it.

@@ -2,6 +2,7 @@
# Do not make an environment from this file, use test.txt instead!

hypothesis
ipympl
Copy link
Member

Choose a reason for hiding this comment

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

Could you use something like plopp[interactive] instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

I tried this now but I messes things up in the nightly dependencies, where we want to get plopp and mpltoolbox from @main... :-(


@pytest.fixture()
def _use_ipympl():
matplotlib.use('module://ipympl.backend_nbagg')
Copy link
Member

Choose a reason for hiding this comment

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

Does this only apply to a single test? It looks like it switches to the ipympl backend for all subsequent tests.

Copy link
Member Author

Choose a reason for hiding this comment

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

hmm I thought it was using ipympl for only a given test, but maybe it sets it for all?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok it is indeed setting it for all the other tests

Copy link
Member Author

Choose a reason for hiding this comment

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

I think I managed to fix this by switching to ipympl for the test and switching back to matplotlib defaults after the test.

# Copyright (c) 2024 Scipp contributors (https://github.com/scipp)

import json
import tempfile
Copy link
Member

Choose a reason for hiding this comment

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

Please use pytest.tmp_path https://docs.pytest.org/en/6.2.x/tmpdir.html#the-tmp-path-fixture instead. This makes sure the files get cleaned up properly but still allows you to inspect them after the test ran.

Copy link
Member

Choose a reason for hiding this comment

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

Does it make sense to make the click API public? It is jot great to rely on implementation details in tests. And maybe, this could be useful for building UIs in the future where we may have some initial masks. But this may be too hypothetical...

Copy link
Member Author

Choose a reason for hiding this comment

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

Does it make sense to make the click API public? It is jot great to rely on implementation details in tests

Not sure; once we add it it's more difficult to hide/remove it again.
What would it look like? A .click(x, y) method which would look up which tool is curently active and forward to that tool?

And maybe, this could be useful for building UIs in the future where we may have some initial masks. But this may be too hypothetical...

I think that is an edge case far away in the future.

"h._tool.click(0, -20)\n",
"h._tool.click(0, -10)\n",
"\n",
"masking_tool.filename.value = \"masks-2d.h5\""
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
"masking_tool.filename.value = \"masks-2d.h5\""
"masking_tool.filename.value = \"masks-2d.json\""

"v._tool.click(20, 150)\n",
"v._tool.click(40, 150)\n",
"\n",
"masking_tool.filename.value = \"masks-1d.h5\""
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
"masking_tool.filename.value = \"masks-1d.h5\""
"masking_tool.filename.value = \"masks-1d.json\""

"metadata": {},
"outputs": [],
"source": [
"masking_tool"
Copy link
Member

Choose a reason for hiding this comment

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

Can you add an explanation for how to manipulate masks? I found myself clicking around a lot and accidentally creating a lot of masks.

Copy link
Member Author

@nvaytet nvaytet Jun 7, 2024

Choose a reason for hiding this comment

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

I added instructions in the docstring and a help button that has a tooltip with instructions.
I unfortunately could not add just an icon with a tooltip, it had to be a button, but clicking the button does nothing (see jupyter-widgets/ipywidgets#3703 (comment)).

I experimented with having hidden instructions that would appear if you clicked the button but in the end, this was the simplest and didn't mess up the layout of the figure.

Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to remove masks? It would not be great to have to start over every time you accidentally add a new mask (easy by misclicking).

Also, an undo button would go a long way. But that might be difficult and a task for another PR.

Copy link
Member Author

Choose a reason for hiding this comment

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

Is it possible to remove masks?

You can remove them by middle-clicking. I added this to the instructions.

Also, an undo button would go a long way. But that might be difficult and a task for another PR.

Yes, difficult and annoying. We'd have to keep a history etc...

disabled=ndim == 1,
**common,
)
self.controls = [rects, vspans, hspans]
Copy link
Member

Choose a reason for hiding this comment

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

These tools don't have tooltips.

@@ -5,7 +5,7 @@ description: Neutron scattering tools for Data Reduction
max_python: '3.12'
min_python: '3.10'
namespace_package: ''
nightly_deps: scipp,scippnexus,plopp
nightly_deps: scipp,scippnexus,plopp,mpltoolbox
Copy link
Member Author

Choose a reason for hiding this comment

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

I had to edit this manually because it was needed for the nightly deps and I didn't want to do a copier update at the same time

• Left-click a vertex to edit a shape
• Right-click and hold to drag a shape
• Middle-click (or Ctrl + left-click) to delete a shape
• Save the masks to a file when the "Save" button is clicked
Copy link
Member

Choose a reason for hiding this comment

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

What are these bullet characters? Are they rendered properly by Sphinx?

Copy link
Member Author

Choose a reason for hiding this comment

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

I made bullets in the tooltip, and copy/pasted. I'll change to -.

@jl-wynen
Copy link
Member

One last comment that may be hard to find in the list: #521 (comment)

@nvaytet nvaytet merged commit a6f8d2a into main Jun 11, 2024
4 checks passed
@nvaytet nvaytet deleted the masking-tool branch June 11, 2024 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

2 participants