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

Line plot widget from layer Metadata for plugins #63

Closed
wants to merge 4 commits into from

Conversation

zoccoler
Copy link
Contributor

@zoccoler zoccoler commented Dec 9, 2022

Hi @dstansby, hi everyone,

I am leaving my suggested changes for this new feature in this PR. This implementation would fullfil #60 .

I don't necessarily expect this to be reviewed soon, so please take your time! :)
On the other hand, please do let me know as soon as possible if these changes can be implemented here so that I can update other repositories that rely on this feature. I am open for changes and feedback!

Best,
Marcelo

@dstansby
Copy link
Member

I'm 👍 for including this. It looks like napari layers have a .features attribute, which stores the kind of data you mentioned in #60 - could you use that to get the data for plotting instead, as it's a built in and documented napari attribute?

@zoccoler
Copy link
Contributor Author

Hi @dstansby ,
All napari layers have the .features attribute except the Image Layer. When I started this, I was aiming for features that would be stored in a image layer, thus the reason for the .metadata.

I would be OK to change from .metadata to .features, which would make it looks similar to the FeatureScatterWidget, then we would not support the image layer.

@dstansby dstansby added the New feature New feature or request label May 3, 2023
@dstansby
Copy link
Member

That makes sense, I didn't realise .metadata was a 'proper' napari layer attribute for some reason - I'll go ahead and review now!

Copy link
Member

@dstansby dstansby left a comment

Choose a reason for hiding this comment

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

Before reviewing this fully, I've left some questions/comments. I thnk there are a few places where this can be slimmed down to make it simpler and easier to review.

src/napari_matplotlib/line.py Outdated Show resolved Hide resolved
Comment on lines +17 to +18
# opacity value for the lines
_line_alpha = 0.5
Copy link
Member

Choose a reason for hiding this comment

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

To keep things simple I think we should just use the default Matplotlib settings, so remove this custom alpha setting.

class Line2DBaseWidget(NapariMPLWidget):
# opacity value for the lines
_line_alpha = 0.5
_lines = []
Copy link
Member

Choose a reason for hiding this comment

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

What's the motivation for saving a list of lines as a class attribute?

def __init__(self, napari_viewer: napari.viewer.Viewer):
super().__init__(napari_viewer)

self.axes = self.canvas.figure.subplots()
Copy link
Member

Choose a reason for hiding this comment

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

The easier and recommended (because it sets up the right theme for the axes) way to do this - I think this is new since this PR was opened.

Suggested change
self.axes = self.canvas.figure.subplots()
self.add_single_axes()

super().__init__(napari_viewer)

self.axes = self.canvas.figure.subplots()
self.update_layers(None)
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure this needs to be here?

def __init__(self, napari_viewer: napari.viewer.Viewer):
super().__init__(napari_viewer)
self.setMinimumSize(200, 200)
self._plugin_name_widget = magicgui(
Copy link
Member

Choose a reason for hiding this comment

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

I'm confused about what the plugin_name stuff is for - could you explain?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was because I thought about a scenario where there are multiple plugins saving/loading settings/features in a layer metadata. If these features have the same name, there would be overwriting problems. That is also why I started with a nested dictionary, as a way to isolate them. What do you think?
We could also drop this level, it would be more up to the user to know that this can happen.

if len(self.layers) == 0:
return []
else:
metadata = self.layers[0].metadata
Copy link
Member

Choose a reason for hiding this comment

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

Would it be possible to get the metadata from all the layers? That way if more than one layer was selected you could choose from metadata in any of the selected layers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is a good idea!


def _get_valid_metadata_keys(
self) -> List[str]:
"""Get metadata keys if nested dictionaries"""
Copy link
Member

Choose a reason for hiding this comment

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

What's the motivation for supporting nested dicts here? I think we should try and make the implementation as simple as possible to start with, which I think means just supporting items in the metadata dictionary that have string keywords and np.ndarray values.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is related to the plugin_name question here.

@zoccoler
Copy link
Contributor Author

Hi @dstansby ,

Thanks for the review and sorry for the long delay! I can restart working on this next week, I am leaving a few comments now.

Recently, a line plot widget from the features property has shown more useful to me (despite not working with the image layer), similar to the already existing FeaturesScatterWidget. Thus, I intend to add it as a second class here as well. Maybe both can be just one, not sure yet if that's a good idea.

Co-authored-by: David Stansby <[email protected]>
@dstansby
Copy link
Member

Stepping back a bit, is there a specified structure for the .metadata attribute in napari? The .features attribute is always a pandas DataFrame, so it's easy to write code that plots it. Without a similar fixed structure for .metadata I'm not sure it's a good idea to support what we're guessing is stored in there. Sorry it's taken me so long to ask this (important!) question...

@zoccoler
Copy link
Contributor Author

Stepping back a bit, is there a specified structure for the .metadata attribute in napari? The .features attribute is always a pandas DataFrame, so it's easy to write code that plots it. Without a similar fixed structure for .metadata I'm not sure it's a good idea to support what we're guessing is stored in there. Sorry it's taken me so long to ask this (important!) question...

Yeah as I said recently, I was working with metadata in order to get features stored in an Image layer, thus the metadata, but I am leaning towards Labels layer anyway. I am refactoring this code to make line plots for the Labels layer.
If it is OK with you, I would close this PR and open a new one where I have been updating this code.

@dstansby
Copy link
Member

👍 closing and opening a new PR is good for me

@zoccoler
Copy link
Contributor Author

zoccoler commented Jul 3, 2023

Closing this as #184 was just opened and should replace this.

@zoccoler zoccoler closed this Jul 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
New feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants