8000 Copy units from layer to layer by Czaki · Pull Request #7727 · napari/napari · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Copy units from layer to layer #7727

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

Merged
merged 10 commits into from
May 5, 2025
Merged

Copy units from layer to layer #7727

merged 10 commits into from
May 5, 2025

Conversation

Czaki
Copy link
Collaborator
@Czaki Czaki commented Mar 19, 2025

References and relevant issues

Description

Add copying units between layers using clipboard

@Czaki Czaki requested review from DragaDoncila, psobolewskiPhD and a team as code owners March 19, 2025 15:52
@github-actions github-actions bot added tests Something related to our tests qt Relates to qt labels Mar 19, 2025
@Czaki Czaki requested a review from GenevieveBuckley March 19, 2025 15:52
@Czaki Czaki added this to the 0.6.1 milestone Mar 19, 2025
Copy link
codecov bot commented Mar 19, 2025

Codecov Report

Attention: Patch coverage is 92.59259% with 2 lines in your changes missing coverage. Please review.

Project coverage is 92.95%. Comparing base (f71b773) to head (b7b39e4).
Report is 27 commits behind head on main.

Files with missing lines Patch % Lines
...ari/_qt/_qapp_model/qactions/_layerlist_context.py 86.66% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7727      +/-   ##
==========================================
- Coverage   92.98%   92.95%   -0.03%     
==========================================
  Files         635      635              
  Lines       59857    59881      +24     
==========================================
+ Hits        55656    55665       +9     
- Misses       4201     4216      +15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor
@GenevieveBuckley GenevieveBuckley left a comment

Choose a reason for hiding this comment

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

This works really well, and I like it a lot.

I have:

  • reviewed the code, and left one or two very minor comments,
  • checked out the branch to play with the feature on my local computer. I've tried the new feature from both the GUI and the terminal, and it's really nice to use.

Thank you for making this happen @Czaki

@@ -90,6 +93,21 @@ def test_copy_scale_to_clipboard(layer_list):
npt.assert_array_equal(layer_list['l2'].translate, (0, 0))


@pytest.mark.usefixtures('qtbot')
def test_copy_units_to_clipboard(layer_list):
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you write a short docstring describing what the test does?
Maybe something like:

Copy-paste spatial units from layer l1 to selected layer l2. Leaves unselected layer l3 unaffected.

Ideally we'd have something like this for all tests in this file, but I understand restricting this PR to just the part you are working on today.

Copy link
Contributor

Choose a reason for hiding this comment

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

Why I suggest this: because developers unfamiliar with this section of the code have to do a bit of scrolling between the layerlist fixture object, and the test cases, before they can figure out what the test is supposed to check.

A short description would be especially helpful here because the tests are checking two things here (1) that the copy-paste works for selected layers, and (2) unselected layers are not affected.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

added

Copy link
Contributor
@DragaDoncila DragaDoncila left a comment

Choose a reason for hiding this comment

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

This looks good and I've pulled it down and played with it. One thing we may want to consider is copying from more ndim to fewer ndim works ok, but copying from fewer ndim to more ndim does not.

Why do we think it's ok to take the last n dimensions from a layer with more dimensions, and assign that to a layer with fewer dimensions, but not take all dimensions from a lower dimension layer and assign it into the last n dimensions of a higher dimension layer? I understand that we can't change the first dimensions (the ones that are unmatched), but it feels like if we're doing it one way, we should do it the other way too.

@@ -104,7 +120,9 @@ def _paste_spatial_from_clipboard(ll: LayerList) -> None:
for layer in ll.selection:
for key in loaded:
loaded_attr_value = loaded[key]
if isinstance(loaded_attr_value, list):
if key == 'units':
loaded_attr_value = loaded_attr_value[-layer.ndim :]
Copy link
Contributor

Choose a reason for hiding this comment

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

why is it ok here to only get the last ndim values for units? Are we assuming that if the layer we copied from has more dimensions than the layer we're pasting to, the shared dimensions are the last ones? Just for my own understanding.

Copy link
Contributor

Choose a reason for hiding this comment

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

Those are good questions, I didn't think to try mismatched dimensions. I'm also interested in the answer

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In general, if the target layer has fewer dimensions than the source one, we need to decide which use.
As we do not have named axis yet, I follow here the viewer semantic and get information from last axes.

Same as in line 137 of this file

(or on main)

loaded_attr_value = loaded_attr_value[-layer.ndim :]

@Czaki
Copy link
Collaborator Author
Czaki commented Mar 28, 2025

@DragaDoncila

This looks good and I've pulled it down and played with it. One thing we may want to consider is copying from more ndim to fewer ndim works ok, but copying from fewer ndim to more ndim does not.

Yes. This is intended to avoid guessing. And it is same for all spatial metadata, not only units. Under the hood it uses layer.property_name = property_value that requires fitting dimensions. If you think that we should implement coping into higher dimension I prefer to do this in separate PR to fix all metadata setting at same.

And the question is if only coping should works, or also assignment of attribute.

@DragaDoncila
Copy link
Contributor

If you think that we should implement coping into higher dimension I prefer to do this in separate PR to fix all metadata setting at same.

@Czaki I guess I would be tempted to simply fail if the dimensions of the layers don't match, but maybe that's too stringent and limits usability of the feature...

And the question is if only coping should works, or also assignment of attribute.

Regardless of what we decide, I think this should only ever work when the user chooses to copy via the context menu. If you're programmatically assigning an attribute, it should do no guesswork whatsoever, and only work if the given attribute's dimensions are correct.

@Czaki
Copy link
Collaborator Author
Czaki commented Apr 18, 2025

@Czaki I guess I would be tempted to simply fail if the dimensions of the layers don't match, but maybe that's too stringent and limits usability of the feature...

I understand. But it is not trivial. And the current implementation in this PR is consistent with coping other spatial information.
Merging this PR without fixing it for upper dimensions allows me to easier work on impacting units on rendering. I may open proper issue before merging this PR to not lost this enhancement.

Copy link
Contributor
@DragaDoncila DragaDoncila left a comment

Choose a reason for hiding this comment

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

Ok I think this is fine to go in then, just left some spell-check fixes but otherwise approving. Thanks for the additional info @Czaki

Co-authored-by: Draga Doncila Pop <17995243+DragaDoncila@users.noreply.github.com>
@DragaDoncila DragaDoncila added ready to merge Last chance for comments! Will be merged in ~24h and removed tests Something related to our tests qt Relates to qt ready to merge Last chance for comments! Will be merged in ~24h labels Apr 22, 2025
@Czaki Czaki added the ready to merge Last chance for comments! Will be merged in ~24h label May 1, 2025
@Czaki Czaki merged commit 368e981 into napari:main May 5, 2025
44 of 49 checks passed
@Czaki Czaki deleted the copy_units branch May 5, 2025 09:47
@github-actions github-actions bot removed the ready to merge Last chance for comments! Will be merged in ~24h label May 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0