-
Notifications
You must be signed in to change notification settings - Fork 2
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 as_popup #101
Add as_popup #101
Conversation
This does not seem ready to be reviewed. |
Forgot to mention at the end, I think I wanted feedback before adding tests, i.e. what you envision for two popups. |
Can you run the pre-commit? |
CodSpeed Performance ReportMerging #101 will not alter performanceComparing Summary
|
Added functionality where double click clears, click anywhere shows the widgets, click on select shows the widgets + delete. Screen.Recording.2024-04-23.at.3.50.52.PM.mov |
I dropped some HoloNote original behavior so that it doesn't require re-clicking the same glyph upon changing from "+" to "-" and vice versa. Screen.Recording.2024-04-24.at.7.49.14.AM.mov |
Okay this is ready for review when you have the time. |
How do these changes affect annotation when you are not using the pop-up? |
it works the same way if I'm not mistaken (must have holoviz/holoviews#6207 alongside): Screen.Recording.2024-04-30.at.6.48.39.AM.movyou can also have it both: import panel as pn
import numpy as np
import pandas as pd
import hvplot.pandas
import numpy as np
import holoviews as hv
from holonote.annotate import SQLiteDB, Annotator
from holonote.app import PanelWidgets
pn.extension()
curve = pd.read_parquet("assets/example.parquet").hvplot(x="TIME")
connector = SQLiteDB(table_name="test_app")
fields = ["Stoppage", "Reason", "Category"]
annotator = Annotator({"TIME": np.datetime64}, fields=fields, connector=connector)
annotator_element = annotator * curve
fields_values = {
"Stoppage": ["Yes", "No"],
"Category": ["Mechanical", "Electrical", "Process", "Other"],
}
w = PanelWidgets(annotator, field_values=fields_values, as_popup=True)
pn.Row(w, annotator_element).show() Screen.Recording.2024-04-30.at.7.02.33.AM.mov |
Same thing if you want to edit? And what if you don't use the Panel widgets at all? |
Can you clarify what you mean? |
Does this work if you have don't use |
Okay, the edit tool works by untangling the tap + double tap:
Screen.Recording.2024-04-30.at.8.38.11.AM.movThe tutorials also work AFAIK |
When you get the chance, would appreciate another review. |
I'm playing around with this PR as we speak. |
Likely, a change happened in Bokeh 3.4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, this PR is in a good state.
I noticed that after you double-click, you will get two pop-ups, making for a confusing experience.
screenrecord-2024-05-06_17.01.01.mp4
Another thing is sometimes I see the pop-up "collapsing". What I mean by this is the inside of the pop-up becomes invisible, and the pop-up is empty with only the x
before it disappears completely.
I'm also not a very big fan of the comment # Rerun to avoid
I couldn't recreate it in Jupyter, but it could be a VSCode-only problem. I think we should be able to remove this problem (not sure where exactly).Models must be owned by only a single document.
Yes I agree that the two popups is annoying, but I have no idea how to prevent it (they're the same panel). Maybe @philippjfr has an idea?
I think this could be fixed by changing the order of things
Not sure how to handle too. |
Yeah, I just saw your comment in HoloViews.
The first step is you describe where you are seeing the problem 🙂 |
Unless you have two separate streams attached I don't think it should be possible to have multiple. If you do have multiple streams you probably just need to toggle visibility on one when you open the other. |
Yes, we have a double tap + box select stream. They both use the same Panel layout, but potentially we could create a dict to track them? |
layouts are now tracked and if one popup is visible, the others are made invisible Screen.Recording.2024-05-06.at.8.46.18.PM.movAlso, was applying this and it works decently: from holonote.annotate import Annotator
from holonote.app import PanelWidgets
import xarray as xr
import panel as pn
import holoviews as hv
hv.extension("bokeh")
ds = xr.tutorial.open_dataset("air_temperature")
def plot_image(time):
image = hv.Image(ds.sel(time=time), ["lon", "lat"], ["air"]).opts(
cmap="RdBu_r", title=time, colorbar=True, clim=(220, 340), width=500, height=300
)
return image
def plot_timeseries_by_select(indices):
if indices:
row = annotator.df.loc[indices[0]]
lon1 = row["start[lon]"]
lon2 = row["end[lon]"]
lat1 = row["start[lat]"]
lat2 = row["end[lat]"]
ds_sel = ds.sel(lon=slice(lon1, lon2), lat=slice(lat2, lat1)).mean(
["lat", "lon"]
)
time_series.object = hv.Curve(ds_sel["air"]).opts(
title=f"Time Series {lon1:.2f} {lat1:.2f} {lon2:.2f} {lat2:.2f}", width=500
)
def plot_timeseries_by_stream(bounds):
if not bounds:
lon1, lat1, lon2, lat2 = ds.lon.min(), ds.lat.min(), ds.lon.max(), ds.lat.max()
ds_sel = ds
else:
lon1, lat1, lon2, lat2 = bounds
ds_sel = ds.sel(lon=slice(lon1, lon2), lat=slice(lat2, lat1))
time_series.object = hv.Curve(ds_sel["air"].mean(["lat", "lon"])).opts(
title=f"Time Series {lon1:.2f} {lat1:.2f} {lon2:.2f} {lat2:.2f}", width=500
)
times = ds.time.dt.strftime("%Y-%m-%d %H:%M").values.tolist()
# start annotation
annotator = Annotator({"lon": float, "lat": float}, fields=["Description", "Time", "Z"])
annotator_widgets = PanelWidgets(
annotator, field_values={"Time": times, "Z": 100}, as_popup=True
)
# make image dependent on the selected time
time_input = annotator_widgets.fields_widgets[1]
time_input.value = times[0]
image = hv.DynamicMap(pn.bind(plot_image, time_input))
time_series = pn.pane.HoloViews()
# update plot time when a new box is SELECTED
pn.bind(plot_timeseries_by_select, annotator.param.selected_indices, watch=True)
# update plot time when a new box is CREATED
display = annotator.get_display("lat", "lon")
box_stream = display._edit_streams[0] # to make public later
box_stream.source = image
pn.bind(plot_timeseries_by_stream, box_stream.param.bounds, watch=True)
# layout
pn.Row(annotator_widgets, pn.Column(annotator * image, time_series)).show() Screen.Recording.2024-05-06.at.8.44.52.PM.movI think we need to make _edit_streams public, and also maybe have a param to disable resetting/refreshing/clearing the widgets value. |
I have no objections to this. I think we should do this in another PR.
That is also OK with me and can be done in this PR. |
Merging if no objections~ |
Upon completing region to highlight, a popup appears with the widgets
Clicking anywhere will popup widgets to allow editing / committing
Screen.Recording.2024-04-24.at.8.48.58.AM.mov