S
Solara3mo ago
pikaa

Plotly FigureWidget axes do not reset ranges within solara's render context

Upon applying an effect to set autorange=True to a figure with autorange='reversed', the Figure does not return to the original axes orientation. I'm wondering what happens behind the scenes here for the render when the use_effect is triggered. I can upload a ipynb with its expected behaviour within a jupyter context vs its behaviour in solara. The partial code (can give complete if needed). plotstate contains 2 reactives for flipx and flipy.
def imshowfig()
def create_fig():
z, cmin, cmax = perform_binning()
fig = px.imshow(z.T,
zmin=cmin,
zmax=cmax,
origin="lower",
color_continuous_scale="inferno")
return fig

# only instantiate the figure once
figure = sl.use_memo(create_fig, dependencies=[])

def add_effects(fig_element: sl.Element):

def set_xflip():
print("setting xflip", plotstate.flipx.value)
fig_widget: FigureWidget = sl.get_widget(fig_element)
if plotstate.flipx.value:
fig_widget.update_xaxes(autorange="reversed")
else:
fig_widget.update_xaxes(autorange=True)
print(fig_widget.layout.xaxis)

def set_yflip():
print("setting yflip", plotstate.flipy.value)
fig_widget: FigureWidget = sl.get_widget(fig_element)
if plotstate.flipy.value:
fig_widget.update_yaxes(autorange="reversed")
else:
fig_widget.update_yaxes(autorange=True)
print(fig_widget.layout.yaxis)

sl.use_effect(set_xflip, dependencies=[plotstate.flipx.value])
sl.use_effect(set_yflip, dependencies=[plotstate.flipy.value])

fig_el = sl.FigurePlotly(figure)
add_effects(fig_el)
def imshowfig()
def create_fig():
z, cmin, cmax = perform_binning()
fig = px.imshow(z.T,
zmin=cmin,
zmax=cmax,
origin="lower",
color_continuous_scale="inferno")
return fig

# only instantiate the figure once
figure = sl.use_memo(create_fig, dependencies=[])

def add_effects(fig_element: sl.Element):

def set_xflip():
print("setting xflip", plotstate.flipx.value)
fig_widget: FigureWidget = sl.get_widget(fig_element)
if plotstate.flipx.value:
fig_widget.update_xaxes(autorange="reversed")
else:
fig_widget.update_xaxes(autorange=True)
print(fig_widget.layout.xaxis)

def set_yflip():
print("setting yflip", plotstate.flipy.value)
fig_widget: FigureWidget = sl.get_widget(fig_element)
if plotstate.flipy.value:
fig_widget.update_yaxes(autorange="reversed")
else:
fig_widget.update_yaxes(autorange=True)
print(fig_widget.layout.yaxis)

sl.use_effect(set_xflip, dependencies=[plotstate.flipx.value])
sl.use_effect(set_yflip, dependencies=[plotstate.flipy.value])

fig_el = sl.FigurePlotly(figure)
add_effects(fig_el)
4 Replies
MaartenBreddels
MaartenBreddels3mo ago
Not sure what is going on here, the code seems correct (and quite nice/creative!). Would be nice if you can could share the code.
pikaa
pikaa3mo ago
Here it is. I was hitting character limit, so I just originally sent that snippet. I've additionally added another plot for a basic scatterplot, where it also doesn't unflip.
MaartenBreddels
MaartenBreddels3mo ago
def create_fig():
z, cmin, cmax = perform_binning()
fig = px.imshow(z.T,
zmin=cmin,
zmax=cmax,
origin="lower",
color_continuous_scale="inferno")
return fig

# only instantiate the figure once
figure = sl.use_memo(create_fig, dependencies=[])
figure.update_xaxes(autorange="reversed" if plotstate.flipx.value else True)
figure.update_yaxes(autorange="reversed" if plotstate.flipy.value else True)


sl.FigurePlotly(figure, dependencies=[plotstate.flipx.value, plotstate.flipy.value])
def create_fig():
z, cmin, cmax = perform_binning()
fig = px.imshow(z.T,
zmin=cmin,
zmax=cmax,
origin="lower",
color_continuous_scale="inferno")
return fig

# only instantiate the figure once
figure = sl.use_memo(create_fig, dependencies=[])
figure.update_xaxes(autorange="reversed" if plotstate.flipx.value else True)
figure.update_yaxes(autorange="reversed" if plotstate.flipy.value else True)


sl.FigurePlotly(figure, dependencies=[plotstate.flipx.value, plotstate.flipy.value])
This works for me, i'm not sure why the updating of the widget doesnt work. It could be an issue with the code, or with the plotly widget. Anyway, I think this is much cleaner, what do you think?
pikaa
pikaa3mo ago
While this works, it refreshes the widget, meaning any user relayout (i.e. zoom & pan) is lost. I'd ideally like to update the property using an effect to keep the current range during the flip updates.