Remove a layout

Hi everyone !
Within the framework of the realization of an interface, I would like to put in a plot a “BoxAnnotation” which represents my robot in a surface of 2meters by 2meters. I just did it, but now my robot will move, and i will receive new position (x/y). Then i have to clear last position and give a new one. And I managed to do that too, but I can’t find the function to remove the “BoxAnnotation”.

I try to use the function “rerderers”, but i think i didnt correctly use her.

this is my code : I clear all useless function, but i dont touch all import (some of them are useless)

from bokeh.plotting import figure, output_file
from bokeh.models import Panel, Tabs
import numpy as np
import math
from bokeh.io import curdoc
from bokeh.io import output_notebook, show
output_notebook()
from bokeh.layouts import column, row
from bokeh.models.widgets import TextInput, Button, Paragraph
from bokeh.models import LinearAxis, Range1d,CheckboxButtonGroup,PreText,Select,CustomJS, ColumnDataSource, Slider, Panel, Tabs
from random import *
from bokeh.driving import count
import numpy as np
import time
from bokeh.models.annotations import BoxAnnotation
    
UPDATE_INTERVAL = 250

def GetPosRobot(p, source):
    global interface4_data
    dxRobot = int(interface4_data['xRobot'])
    dyRobot = int(interface4_data['yRobot'])
    p.circle(dxRobot, dyRobot, color='pink')
    xlrobot = dxRobot + 10.5
    xrrobot = dxRobot - 10.5
    ytrobot = dyRobot + 12
    ybrobot = dyRobot - 12
    robot = BoxAnnotation(top = ytrobot, bottom = ybrobot, left = xlrobot, right = xrrobot, fill_alpha=0.1, fill_color='blue')
    p.add_layout(robot)
    return None
         
def update():
    global interface4_data, p
    N = 1
    interface4_data = dict(xRobot = np.random.random(size=N) * 200,yRobot = np.random.random(size=N) * 200)
    GetPosRobot(p, interface4_data)
    for i in range(N):
        print(interface4_data['xRobot'])
        print(interface4_data['yRobot'])
           
p = figure(x_range=(0, 200), y_range=(0, 200))

doc=curdoc() fois
doc.add_root(p)
doc.add_periodic_callback(update, UPDATE_INTERVAL)

@Aemeris Why are you using a BoxAnnotation for this instead of one of the “box” glyph types e.g. quad or rect? Then you could update the position by updating the data source for the glyph. Even with the BoxAnnotation you can update the properties of the existing box annotation, rather than deleting an old one and and adding a new one. Updating existing objects is always definitely a more recommended best practice. If the issue is the box needs to not be shown at certain times then you can set the .visible property of either an annotation or a glyph to False (again, update existing better than remove/add)

Hi Bryan!

I may have chosen too quickly to use a “boxAnnotation”. But that said I decided to make my interface with it simply because visually I liked it.

I actually finished with a BoxAnnotation, with ur solution, thank you indeed it was easier to update()

thats the solution :

        in UPDATE_INTERVAL = 1000 

def Xrrobot(dxRobot):
    xrrobot = dxRobot - 10.5    
    return xrrobot

def Xlrobot(dxRobot):
    xlrobot = dxRobot + 10.5
    return xlrobot

def Ytrobot(dyRobot):
    ytrobot = dyRobot + 12
    return ytrobot

def Ybrobot(dyRobot):
    ybrobot = dyRobot - 12
    return ybrobot


def GetPositionZone():
    #en x
    # zoneInexploreD = BoxAnnotation(top = ytrobot, bottom = ybrobot, left = 0, right = xrrobot, fill_alpha=0.1, fill_color='olive')
    # p.add_layout(zoneInexploreD)
    
    # zoneInexploreG = BoxAnnotation(top = ytrobot, bottom = ybrobot, left = xrrobot, right = 200, fill_alpha=0.1, fill_color='olive')
    # p.add_layout(zoneInexploreG)
    # #en y
    # zoneInexploreB = BoxAnnotation(top = ybrobot, bottom = 0, left = 0, right = 200, fill_alpha=0.1, fill_color='olive')
    # p.add_layout(zoneInexploreB)
    
    # zoneInexploreH = BoxAnnotation(top = 200, bottom = ytrobot, left = 0, right = 200, fill_alpha=0.1, fill_color='olive')
    # p.add_layout(zoneInexploreH)
    return

def update():
    global interface4_data, p
    N = 1
    interface4_data = dict(xRobot = np.random.random(size=N) * 200,yRobot = np.random.random(size=N) * 200)
    dxRobot = int(interface4_data['xRobot'])
    dyRobot = int(interface4_data['yRobot'])
    p.circle(dxRobot, dyRobot, color='pink')   
    robot.top = Ytrobot(dyRobot)
    robot.bottom = Ybrobot(dyRobot)
    robot.left = Xlrobot(dxRobot)
    robot.right = Xrrobot(dxRobot)

    

# , "Positionxdroite":[], "Positionxgauche":[], "Positionydroite":[], "Positionygauche":[]
# interface4_data = dict(xRobot =np.random.random(size=N) * 100,y=np.random.random(size=N) * 100)

p = figure(x_range=(0, 200), y_range=(0, 200))
robot = BoxAnnotation(top = 0, bottom = 0, left = 0, right = 0, fill_alpha=0.1, fill_color='blue')
p.add_layout(robot)
doc=curdoc() #il va recréer un nouveau document a chaque fois
doc.add_root(p)
doc.add_periodic_callback(update, UPDATE_INTERVAL)