I’m currently trying to bring in some data through np, do some processing on that initial data, plot it, but then be interactive with my plot. Plotly has a tutorial of how to take the plot and change the color of the data points (in jupyter using the click event https://plotly.com/python/click-events/). What I’m hoping to do is be able to take the click event click on 2 points and then create a line between the points selected and gather my positions of the line. The only thing I have found in plotly is just hovering over the data but not being able to do this processing. Is there a better way of doing this rather than using plotly? The documentation on plotly is suggesting to just use dash, but I haven’t found a way of doing this with dash. The follow-up question would be how do I get this data if I export my plot (fig.write_html
)?
Sample of what I have is:
import matplotlib matplotlib.use('TkAgg') import matplotlib.pyplot as plt # Import libraries import pandas as pd import numpy as np import plotly.express as px import plotly.graph_objects as go x=np.random.uniform(-10,10,size=50) y=np.sin(x) fig=go.FigureWidget([go.Scatter(x=x, y=y, mode='markers')]) fig.update_layout(template='simple_white') scatter=fig.data[0] colors=['#a3a7e4']*100 scatter.marker.color=colors scatter.marker.size=[10]*100 fig.layout.hovermode='closest' fig.update_traces(marker=dict(line=dict(color='DarkSlateGrey'))) # create our callback function def update_point(trace, points, selector): c = list(scatter.marker.color) s = list(scatter.marker.size) for i in points.point_inds: c[i]='#bae2be' s[i]=20 with fig.batch_update(): scatter.marker.color=c scatter.marker.size=s scatter.on_click(update_point) fig
Advertisement
Answer
- given you attempted example is ipwidgets I have extended this
- create an empty trace that will be target for lines
- for debugging create
widgets.Output()
- now just a case of creating UI using
HBox()
andVBox()
- for now have demonstrated how you can export by printing to stdout. This clearly could save the JSON to a file
# Import libraries import pandas as pd import numpy as np import plotly.express as px import plotly.graph_objects as go import json import ipywidgets as widgets x=np.random.uniform(-10,10,size=50) y=np.sin(x) fig=go.FigureWidget([go.Scatter(x=x, y=y, mode='markers'), go.Scatter(x=[], y=[], mode="lines")]) fig.update_layout(template='simple_white') scatter=fig.data[0] line = fig.data[1] colors=['#a3a7e4']*100 scatter.marker.color=colors scatter.marker.size=[10]*100 fig.layout.hovermode='closest' fig.update_traces(marker=dict(line=dict(color='DarkSlateGrey'))) out = widgets.Output(layout={'border': '1px solid black'}) out.append_stdout('Output appended with append_stdoutn') # create our callback function @out.capture() def update_point(trace, points, selector): x = list(line.x) + points.xs y = list(line.y) + points.ys line.update(x=x, y=y) scatter.on_click(update_point) reset = widgets.Button(description="Reset") export = widgets.Button(description="Export") @out.capture() def on_reset_clicked(b): line.update(x=[], y=[]) out.clear_output() @out.capture() def on_export_clicked(b): print(fig.to_dict()["data"][1]) reset.on_click(on_reset_clicked) export.on_click(on_export_clicked) widgets.VBox([widgets.HBox([reset, export]), widgets.VBox([fig, out])])