How to prevent recursion with interactive plot in bqplot?

572 views Asked by At

I created an interactive scatterplot using bqplot where you are allowed to drag points around (using enable_move=True).

I don't want the user to drag points above the line y=x. If they do, I want the point to snap back to where it was most recently.

The problem is that I'm not sure how to avoid infinite recursion here.

The scatterplot needs to be aware of when its points are moved in order to check the move and possibly snap back. However, when it begins to snap back, this change (of the point positions) seems to trigger that same callback.

Can anyone tell me the "correct" way to deal with this basic issue?

import bqplot.pyplot as plt
import numpy as np

def on_point_move(change, scat):
    if np.any(newx < scat.y):
        scat.x = change['old']
    
fig = plt.figure(animation_duration=400)
xs = 1.0*np.arange(3) # make sure these are floats
ys = 1.0*np.arange(3)
scat = plt.scatter(xs, ys, colors=['Red'], default_size=400, enable_move=True)
scat.observe(lambda change: on_point_move(change, scat), names=['x'])
fig
1

There are 1 answers

1
DougR On BEST ANSWER

You can temporarily disable the observe in the on_point_move function. I've changed the logic a bit too.

import bqplot.pyplot as plt
import numpy as np

def on_point_move(change):
    if np.any(scat.x < scat.y):
        scat.unobserve_all()
        if change['name'] == 'x':
            scat.x = change['old']
        elif change['name'] == 'y':
            scat.y = change['old']
        scat.observe(on_point_move, names=['x','y'])
    

fig = plt.figure(animation_duration=400)
xs = 1.0*np.arange(3) # make sure these are floats
ys = 1.0*np.arange(3)
scat = plt.scatter(xs, ys, colors=['Red'], default_size=400, enable_move=True)
scat.observe(on_point_move, names=['x','y'])

fig