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

Modifiable styles & UI editor in Jupyter #1119

Open
banesullivan opened this issue Apr 19, 2023 · 8 comments
Open

Modifiable styles & UI editor in Jupyter #1119

banesullivan opened this issue Apr 19, 2023 · 8 comments
Assignees

Comments

@banesullivan
Copy link
Contributor

@zachmullen and I were brainstorming a style editor for tile sources that would be exposed in Jupyter alongside the interactive viewer in #1065. Here are my thoughts:

  1. Add a style @property to TileSource (a wrapper around the existing _setStyle() method and .style attribute). This will be a clean/simple interface to get/set/update the style on a TileSource.
  2. Create a new TileSourceStyle class extending dict. Have the style property return/leverage this class.
  3. Add convenience functionally to TileSourceStyle that makes it easier to update the style for a specific band in the dictionary or any other neat ideas that come along (more of these can come later)
  4. Add an _ipython_display_ method to TileSourceStyle that returns a set of ipywidgets to control/modify the style. More details below.

_ipython_display_ interface

I think we should start with a minimal style-adjusting interface much like what @jtomeck and I created for django-large-image:

Screen Shot 2023-04-18 at 10 16 53 AM

This will have a tree structure for all the available bands and frames with the ability to:

  • Toggle each band and/or frame on/off
  • Set the color palette (matplotlib colormaps or solid colors)
  • Set the vmin/vmax

Like the django-large-image editor, I think it would be nice to display a thumbnail directly in the widget as well so that users can easily see the styling adjustments.

Use

In Jupyter, users would simply output the .style property at the end of a cell to get the ipywidgets interface:

import large_image
source = large_image.open(
    'path/to/image.tif',
    encoding="PNG",
    projection="EPSG:3857"
)
source.style

TileSourceStyle pseudo code

I think we'll need to keep a reference to the parent tile source so that it is able to reapply itself as it is updated. This will get tricky if trying to share a style across multiple tile sources, so maybe we should brainstorm other approaches.

import weakref

class TileSourceStyle(dict):
    def __init__(self, source, *args, **kwargs):
        super(TileSourceStyle, self).__init__(*args, **kwargs)
        self.source_ = weakref.ref(source)
        
    def _ipython_display_(self):
        ... # return widgets
        
    def update(self):
        self.source_()._setStyle(self)
        
    def __setitem__(self, key, value):
        super().__setitem__(key, value)
        self.update()

Uncertainties

My only uncertainty on building this interface is whether calling _setStyle() is sufficient to update the style on a TileSource instance? @manthey, do you have any thoughts on this or feedback on the pseudo code above?

@banesullivan
Copy link
Contributor Author

The ipywidgets UI would be a start/initial prototype because it is easy to build something polished quickly. Later, we can/should evaluate custom UIs built on Vue that we can expose in multiple environments (for Jupyter, I think leveraging anywidget might support this: https://anywidget.dev/) -- which could then bring this together with work like #1086

@banesullivan
Copy link
Contributor Author

banesullivan commented Apr 19, 2023

Further, a hook/listener would need to be added to the work done in #1065 so that the URL of the tile layer in the ipyleaflet view is invalidated/updated to refresh the newly style image

@jeffbaumes
Copy link
Member

This seems reasonable to me at least at a very high level. In addition to a geo use case, I recommend adding a use case of a multi-channel histology image (e.g. different stains) that could also be manipulated in a reasonable way with this widget. @manthey could probably provide this.

@manthey
Copy link
Member

manthey commented Apr 19, 2023

See also what has been going on in #1086. This is a vue component that might be able to be extended to cover the use cases you have. For instance, currently, you pick a color, not a color map. But, we aim to add more features to it over time and it'd be great if we can harmonize our use cases.

@banesullivan
Copy link
Contributor Author

I agree it would be great to harmonize the use cases and bring all of the UI code together. Maybe its worth looking into custom Vue widgets with anywidget (or another toolkit) now instead of prototyping with ipywidgets (added task to project board)

@jeffbaumes
Copy link
Member

Anywidget looks nice, but a quick look and some searching does not inspire immense confidence in adopting it (e.g. searching "anywidget vue" doesn't seem to surface any good results of people bundling vue with it). In theory it seems it could use any vite-powered build which is cool but anywidget seems a bit boutique use case for very lightweight widgets.

@manthey
Copy link
Member

manthey commented Apr 20, 2023

Currently, we don't expect to change the style except on class instantiation. We store a reference to the source instance in the cache based on the style (amongst other things). Without the source cache, setting the style would just be obtaining the style lock and then calling _setStyle (or doing it in _setStyle, which would necessitate making the style lock before calling that). But, there would then be a disharmony between the class instance and the cache instance.

We could probably resolve this by making _setStyle or the cache retrieval a little more complicated if this is desirable enough.

@manthey
Copy link
Member

manthey commented Mar 21, 2024

This was largely implemented with the noCache=True option when opening a source.

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

No branches or pull requests

4 participants