Find the DnD coordinates when cropping with BoxSelectTool

I want a cross between the BoxSelectTool and BoxEditTool. When I crop a region on my scatter graph, I want to know which dots are selected as well as leave behind a rectangular marker of the selected region. I am using embedded server and callback. Right now, source.selected.on_change(‘indices’,callback) will give me the indices of selected dots, but not the coordinates with which to draw my rectangle. Can someone point out a way to accomplish this?

There is not any way to have a single callback that gets both (short of creating your own custom extension tool) but you can have a separate callback that responds just to the selection geometry event. See this example:

thanks for the code sample. I got it working, but when I tried to use print_event, I get an error
p.js_on_event(events.SelectionGeometry, print_event(attributes=[‘geometry’, ‘final’]))

TypeError: Object of type ‘function’ is not JSON serializable

what is the proper way to call the print_event function in the code?

@bhomass print_event is just something created for that demo, it can be modified to suit your needs, or does not need to be used at all. It’s not anything standard or official in the library. It exists to be very general in order to make an example that covers all possible events. I would suggest you might just want to make a plain function callback, rather than use a generic factory-function for manufacturing callbacks (which is what print_event is)

In any case, please provide the entire stack trace (not just the last line) as well as some of the code context around the line that the exception reports.

I tried writing a simple callback, but I don’t know the right syntax
def event_callback(attributes):

plot.js_on_event(events.SelectionGeometry, event_callback(attributes=['geometry', 'final']))    

the output just says
attributes=['geometry', 'final']

When I use the print_event call, I get
ERROR:bokeh.server.protocol_handler:error handling message
message: Message ‘PULL-DOC-REQ’ (revision 1) content: {}
error: TypeError(“Object of type ‘function’ is not JSON serializable”,)
Traceback (most recent call last):
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/site-packages/bokeh/server/”, line 100, in handle
work = yield handler(message, connection)
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/site-packages/tornado/”, line 735, in run
value = future.result()
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/site-packages/tornado/”, line 748, in run
yielded = self.gen.send(value)
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/site-packages/bokeh/server/”, line 70, in _needs_document_lock_wrapper
result = yield yield_for_all_futures(func(self, *args, **kwargs))
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/site-packages/bokeh/server/”, line 228, in _handle_pull
return connection.protocol.create(‘PULL-DOC-REPLY’, message.header[‘msgid’], self.document)
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/site-packages/bokeh/protocol/”, line 80, in create
return self._messages[msgtype].create(*args, **kwargs)
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/site-packages/bokeh/protocol/messages/”, line 83, in create
content = { ‘doc’ : document.to_json() }
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/site-packages/bokeh/document/”, line 845, in to_json
doc_json = self.to_json_string()
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/site-packages/bokeh/document/”, line 874, in to_json_string
return serialize_json(json, indent=indent)
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/site-packages/bokeh/core/”, line 160, in serialize_json
return json.dumps(obj, cls=BokehJSONEncoder, allow_nan=False, indent=indent, separators=separators, sort_keys=True, **kwargs)
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/json/”, line 238, in dumps
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/json/”, line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/json/”, line 257, in iterencode
return _iterencode(o, 0)
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/site-packages/bokeh/core/”, line 251, in default
return self.transform_python_types(obj)
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/site-packages/bokeh/core/”, line 218, in transform_python_types
return super(BokehJSONEncoder, self).default(obj)
File “/home/bruce/anaconda3/envs/bokeh/lib/python3.6/json/”, line 180, in default
TypeError: Object of type ‘function’ is not JSON serializable

@bhomassyiuo you can’t call js_on_event with a Python callback. First things first: do you want a Python callback, or a JavaScipt callback?

Hi, python callback.

In the case you want on_event, not js_on_event. (Both kinds are used in the example linked.)

my bad. I was under the illusion that the second part was redundant, and delete them after copying. Now it all works.

1 Like