# Interactive plot, acting as a range slider tool for another plot?

**URL:** https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392
**Category:** General Usage
**Created:** [February 3, 2019, 8:30am UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392 "2019-02-03T08:30:42Z")
**Posts on this page:** 19
**Page:** 1

<div class="post-metadata">

### Author: ![sairus7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sairus7/32/10816_2.png) [@sairus7](https://discourse.julialang.org/u/sairus7)
#### Post date: [February 3, 2019, 8:30am UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/1 "2019-02-03T08:30:42Z")

</div>

How can I get in Julia an interactive plot with range slider for another plot?  
Something like this (but not necessary with the same data on both plots):  
[https://bokeh.pydata.org/en/latest/docs/gallery/range\_tool.html](https://bokeh.pydata.org/en/latest/docs/gallery/range_tool.html)  
 ![ex](https://global.discourse-cdn.com/julialang/original/3X/4/5/4569ed161670c5c1463faea8bb4a04923cd75147.jpeg)

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [February 3, 2019, 8:46am UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/2 "2019-02-03T08:46:25Z")

</div>

I don’t even know Julia can take mouse input

---

<div class="post-metadata">

### Author: ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)
#### Post date: [February 3, 2019, 1:33pm UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/3 "2019-02-03T13:33:32Z")

</div>

Yes, it is possible to take mouse input in Julia. I suspect Makie is a good candidate for implementing something like this. The interactive docs are [here](http://makie.juliaplots.org/stable/interaction.html) (they seem slightly outdated as they point to the Reactive package for the underlying logic, whereas [Observables](https://github.com/JuliaGizmos/Observables.jl) is being used now, but I imagine things should work with minimal changes). I’m not sure if a `range_tool` has been implemented though, chances are you may need to implement the logic yourself (meaning, make the larger plot update automatically as soon as the rectangle extremas are changed), which should be done with the `lift` function.

---

<div class="post-metadata">

### Author: ![Jordan\_Cluts](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jordan_cluts/32/13753_2.png) [@Jordan\_Cluts](https://discourse.julialang.org/u/Jordan_Cluts)
#### Post date: [February 3, 2019, 1:45pm UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/4 "2019-02-03T13:45:57Z")

</div>

I did this exact thing once. It can be done using VegaLite.jl

```julia
using DataFrames, VegaLite

function PlotWithFocus(A::DataFrame)
    A |> [
        @vlplot(mark={typ=:line,interpolate="linear"},x={field=:Time,typ=:quantitative,scale={domain={selection=:brush}},axis={title=""}}, y=:Displacement, width=600,height=400,title="Title",background="white");
        @vlplot(selection={brush={typ=:interval,encodings=["x"]}},mark={typ=:line,interpolate="linear"},x={field=:Time,typ=:quantitative}, y=:Displacement, width=600,height=80,background="white")
   ]
end

A=DataFrame(Time = collect(1:100),Displacement=[rand() for _ in 1:100])

PlotWithFocus(A)

```

 ![Slider](https://global.discourse-cdn.com/julialang/original/3X/9/6/96f09944030dd11871da5b9e4965ec56fe4d51df.png)

Here I’ve used the same data for both but that wouldn’t be necessary.

 ![visualization-1](https://global.discourse-cdn.com/julialang/original/3X/7/8/7879740ad27d16d998e38847ac9453d23775a10a.png)

---

<div class="post-metadata">

### Author: ![davidanthoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/davidanthoff/32/223493_2.png) [@davidanthoff](https://discourse.julialang.org/u/davidanthoff)
#### Post date: [February 3, 2019, 7:43pm UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/5 "2019-02-03T19:43:41Z")

</div>

> [@Jordan\_Cluts](#):
>
> I did this exact thing once. It can be done using VegaLite.jl

Very nice! I’ve never really did much with the interactive features in vega-lite, so great to see that it actually all works via our julia wrapper 🙂

---

<div class="post-metadata">

### Author: ![sairus7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sairus7/32/10816_2.png) [@sairus7](https://discourse.julialang.org/u/sairus7)
#### Post date: [February 4, 2019, 11:21pm UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/6 "2019-02-04T23:21:45Z")

</div>

Thank you, this is a really nice example! I’ve made some more complex example with multiple scales: ![visualization](https://global.discourse-cdn.com/julialang/original/3X/e/9/e9a2d4f7eae26464957ad94ec0f0e8bd319c43b6.png)

> **Source code**
>
> ```julia
> using DataFrames, VegaLite
> 
> function PlotWithFocus(A::DataFrame)
> A |> [
> @vlplot(
> mark={typ=:line,interpolate="step-after"},
> x={
> field=:Time,
> typ=:quantitative,
> scale={domain={selection=:brush1}},
> axis={title=""}
> },
> y=:Trend1,
> width=600,
> height=160,
> title="Title",
> background="white"
> );
> @vlplot(
> selection={brush1={typ=:interval,encodings=["x"]}},
> mark={typ=:area},
> x={
> field=:Time,
> typ=:quantitative,
> scale={domain={selection=:brush2}},
> axis={title=""}
> },
> y=:Trend2,
> width=600,
> height=80,
> background="white"
> );
> @vlplot(
> selection={brush2={typ=:interval,encodings=["x"]}},
> mark={typ=:line},
> x={field=:Time,typ=:quantitative},
> y=:Trend3,
> width=600,
> height=80,
> background="white"
> )
> ]
> end
> 
> N = 2000
> 
> function some_data!(X, cX)
> x0 = 0
> s0 = 0
> for i=1:length(X)
> x0 += (X[i] - x0)*0.05
> X[i] = x0
> s0 += x0
> cX[i] = s0
> end
> end
> 
> X = randn(Float32, N)
> cX = similar(X)
> some_data!(X, cX)
> 
> A = DataFrame(
> Time = collect(1:N),
> Trend1 = X,
> Trend2 = X,
> Trend3 = cX,
> )
> 
> PlotWithFocus(A)
> 
> ```

But, the main reason to do multi-scale is to handle large amounts of data at different levels of detail - both for better performance and better visual representation. Some simplified data representation (with less points) can be plotted at full range, and detailed data (with more points) can be plotted with fewer points within a small range.

In this context, I don’t understand:

1. How to plot several datasets with different length? Or more generally, how can I bind plots with diferent data sources (and probably not only DataFrames type)?
2. How to plot large amounts of data efficiently, so they are dynamically loaded on the required range, when the selection is changed? Or more generally, how to bind VegaLite events to some custom Julia functions e.g. for data range selection from a given data sourse. With current solution, interacting with 10k points is already laggy.

---

<div class="post-metadata">

### Author: ![Jordan\_Cluts](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jordan_cluts/32/13753_2.png) [@Jordan\_Cluts](https://discourse.julialang.org/u/Jordan_Cluts)
#### Post date: [February 5, 2019, 3:29pm UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/7 "2019-02-05T15:29:58Z")

</div>

For questions in general the VegaLite.jl Docs are very helpful as is the VegaLite documentation (examples from there require a little translation but it’s not hard). [Here](http://fredo-dedup.github.io/VegaLite.jl/stable/userguide/data/) is where data import is discussed in the context of VegaLite.jl where it describes ingesting csv, json, and a few other file types in addition to the DataFrame support. More detail is provided [here](https://vega.github.io/vega-lite/docs/data.html) from the VegaLite documentation.

I’m not sure what you mean by “datasets with different length”. Since they are being plotted together they must share some sort of axis. If one is missing (for example two time histories where once contains dates the other doesn’t) then one could be padded perhaps? In any case, the transformations provided in VegaLite are very important if one is going to be using it seriously. Particularly the [Filter](https://vega.github.io/vega-lite/docs/filter.html) Transform which can be used to reduce and alter data from various datasets.

As for the large amount of data problem I have had the same issue. It can be tackled to some degree by using Filter so you select only every 50th point or something since all the points cannot be represented on the screen anyway. I have had this issue as well however and have found that for very large datasets (I ran into this problem when I threw about 2 million points at VegaLite) other plotting solutions may be needed. Others may have suggestions on how to squeeze more performance out of VegaLite or other plotting suggestions such as Makie mentioned previously.

It’s also worth noting the VegaLite is Lite for a reason, it’s a simplified interface to the [Vega](https://vega.github.io/vega/examples/) plotting system. Much more complicated data ingestion and transformation is possible with the full Vega system. I believe there has been discussion of a Vega.jl package or similar but I don’t know much about it but the number of points issue would likely remain.

---

<div class="post-metadata">

### Author: ![sairus7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sairus7/32/10816_2.png) [@sairus7](https://discourse.julialang.org/u/sairus7)
#### Post date: [February 5, 2019, 3:54pm UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/8 "2019-02-05T15:54:44Z")

</div>

> [@Jordan\_Cluts](#):
>
> I’m not sure what you mean by “datasets with different length”. Since they are being plotted together they must share some sort of axis. If one is missing (for example two time histories where once contains dates the other doesn’t) then one could be padded perhaps? In any case, the transformations provided in VegaLite are very important if one is going to be using it seriously. Particularly the [Filter](https://vega.github.io/vega-lite/docs/filter.html) Transform which can be used to reduce and alter data from various datasets.

Simply, I have two datasets with different length on the same x-axis:

```julia
dataset1 = DataFrame(xTime = collect(1:100), yTrend = randn(Float32, 100))
dataset2 = DataFrame(xTime = [10, 35, 60, 94], yEvents = [1, 2, 1, 1])

```

---

<div class="post-metadata">

### Author: ![Jordan\_Cluts](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jordan_cluts/32/13753_2.png) [@Jordan\_Cluts](https://discourse.julialang.org/u/Jordan_Cluts)
#### Post date: [February 5, 2019, 4:33pm UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/9 "2019-02-05T16:33:52Z")

</div>

```julia
using DataFrames, VegaLite

function PlotDifferentData(A::DataFrame,B::DataFrame)
    [
        @vlplot(mark={typ=:line,interpolate="linear"},data=A,x={field=:xTime,typ=:quantitative,scale={domain={selection=:brush}},axis={title=""}}, y=:yTrend, width=600,height=400,title="Title",background="white");
        @vlplot(selection={brush={typ=:interval,encodings=["x"]}},data=B,mark={typ=:point},x={field=:xTime,typ=:quantitative}, y=:yEvents, width=600,height=80,background="white")
   ]
end

dataset1 = DataFrame(xTime = collect(1:100), yTrend = randn(Float32, 100))
dataset2 = DataFrame(xTime = [10, 35, 60, 94], yEvents = [1, 2, 1, 1])

PlotDifferentData(dataset1,dataset2)

```

 ![visualization(1)](https://global.discourse-cdn.com/julialang/original/3X/9/1/914dedcf93747078bb65aa362979632e2c45d0e4.png)

It also turns out that VegaLite.jl handles missing values just fine so if you want data sources of different length on the same axes just pad with missing like [this.](http://fredo-dedup.github.io/VegaLite.jl/stable/examples/examples_line_charts/#Line-Chart-with-Markers-and-Invalid-Values-1)

---

<div class="post-metadata">

### Author: ![davidanthoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/davidanthoff/32/223493_2.png) [@davidanthoff](https://discourse.julialang.org/u/davidanthoff)
#### Post date: [February 6, 2019, 1:31am UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/10 "2019-02-06T01:31:15Z")

</div>

> [@Jordan\_Cluts](#):
>
> As for the large amount of data problem I have had the same issue. It can be tackled to some degree by using Filter so you select only every 50th point or something since all the points cannot be represented on the screen anyway. I have had this issue as well however and have found that for very large datasets (I ran into this problem when I threw about 2 million points at VegaLite) other plotting solutions may be needed. Others may have suggestions on how to squeeze more performance out of VegaLite or other plotting suggestions such as Makie mentioned previously.

In my mind there are two distinct issues currently with large datasets:

1. How do you get them into vega-lite? Right now if you start with a very large dataset in julia and plot it with VegaLite.jl, the dataset will essentially be sent in a JSON format to vega-lite (the Javascript part). That can’t be a very efficient way 😉 I think in the short run, maybe one way around that is to save the data as a CSV file and then specify the file as the data source in the vega-lite spec. I’m not really sure that is faster, but it might. Medium/long term I think something base on [Add Arrow/Feather reader · Issue #1300 · vega/vega · GitHub](https://github.com/vega/vega/issues/1300) will probably resolve this issue.
2. The second issue is whether vega-lite can deal with very large datasets, once the transfer problem has been solved. I think right now the javascript part starts to choke with very large datasets (although 10000 seems a number it should still handle fairly easily). I’m not super familiar with the plans of the vega-lite team, but I know this scenario is very much on their radar. I think [GitHub - vega/falcon: Brushing and linking for big data](https://github.com/uwdata/falcon) is a first attempt to tackle this. I have no idea how exactly that work might interact with the julia story in the future, but I would expect we can sort that out somehow eventually.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [February 6, 2019, 8:25am UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/11 "2019-02-06T08:25:39Z")

</div>

> [@davidanthoff](#):
>
> In my mind there are two distinct issues currently with large datasets:

Conceptually, almost all useful plots of _large datasets_ are in fact plots of _very small datasets_ that result from a transformation (binning, quantiles, various combinations of these). Otherwise overplotting makes plots very hard to read.

Making the transformations interactive is very nice, but that results in an application that does much more than plotting. Of course it is nice to leverage something already available, but IMO Julia will soon be at the point that applications like this can be written natively, using some web-based UI, plotting packages, and existing data table management libraries. For very large data, probably the weakest link at the moment is the latter (if the data does not fit in memory).

---

<div class="post-metadata">

### Author: ![sairus7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sairus7/32/10816_2.png) [@sairus7](https://discourse.julialang.org/u/sairus7)
#### Post date: [February 6, 2019, 12:00pm UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/12 "2019-02-06T12:00:47Z")

</div>

CSV can’t be very efficient either - it’s the same text as JSON. For my personal needs I store data just in plain binary files with column format and names (and other metadata) defined in separate header file.

Actually, I would not link plot performance problem with large datasets, because memory limitations for array storage is far beyond the limitations of plotting system. In other words, even relatively small datasets (100k points of Float32 ~ 390KB) can be plotted with lags on interaction, if library is using SVG or Canvas, instead of WebGL. Or if there are no effective caching of invisible data points beyond the visible range. But it can be used for interaction with small datasets or generating static plots, with no interaction.

In Matlab, I’ve made some primitive plot caching mechanism that binds file reading by chunks with plotting a small range of long-term signal. When visual range is changed, It just reads this range with some additional ranges on edges, so there is no need to read file with every small range updates, and big amounts of data can be loaded dynamically on range changes.

---

<div class="post-metadata">

### Author: ![MA\_Laforge](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ma_laforge/32/385_2.png) [@MA\_Laforge](https://discourse.julialang.org/u/MA_Laforge)
#### Post date: [February 9, 2019, 5:34am UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/13 "2019-02-09T05:34:54Z")

</div>

#### Large Datasets

FYI. The InspectDR plotting tool was _ **designed** _ to deal with large datasets (ex: 2Gb+):  
 → [GitHub - ma-laforge/InspectDR.jl: Fast, interactive Julia/GTK+ plots (+Smith charts +Gtk widget +Cairo-only images)](https://github.com/ma-laforge/InspectDR.jl)

InspectDR uses “F1-acceleration” to draw line “glitches” that display the min/max values of a dataset when they are too close to be drawn on different “plot pixels”.

_ **Caveat:** _ F1-acceleration is only active when you plot with lines. This filter generates confusing/misleading plots if you are plotting with “symbols” instead of lines. However, the behaviour can be overwritten if you _ **really** _ want to apply F1-acceleration with symbols.

The GUI is built on Gtk, and I must say it has pretty good interactivity. For example: you can use the mouse to perform a _ **Box zoom** _ - and you can even add “delta” markers to measure slopes, etc:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/e/a/ea47220dc58eae97c9ed29dde1d46b4b8ced2d40.png)

Unfortunately, it does not have that cool capability of using one plot as a slider tool for another, though. That is truly a _ **great feature** _ that VegaLite.jl has there!

---

<div class="post-metadata">

### Author: ![davidanthoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/davidanthoff/32/223493_2.png) [@davidanthoff](https://discourse.julialang.org/u/davidanthoff)
#### Post date: [February 9, 2019, 7:14pm UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/14 "2019-02-09T19:14:42Z")

</div>

This topic came up on the vega slack channel recently. My understanding is that they actually plan a design where the JavaScript part can call back into whatever host language one is using to do the data transformations there, in reaction to interactions. I think the prototype they have is based on SQL, but I believe they plan to also add support on the Python side for pandas and ibis. I think a natural story for julia then would be to use [Query.jl](https://github.com/queryverse/Query.jl) in the same way for that.

In any case, I’m in touch with the vega-lite group, and we’ll probably have a meeting soon to discuss those kinds of things. I still wouldn’t expect anything anytime soon, but folks are thinking about this issue 🙂

---

<div class="post-metadata">

### Author: ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)
#### Post date: [February 10, 2019, 12:19am UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/15 "2019-02-10T00:19:23Z")

</div>

It sounds like Vega is trying to cover functionalities similar to [Bokeh](https://bokeh.pydata.org/en/latest/) plus [datashader](http://datashader.org/). But maybe it would be sufficiently different so that it uses grammar of graphics-like approach and focuses on statistical visualization?

By the way, I think writing Bokeh backend in Julia is another approach for interactive plot for “big data.” I think Julia is a great fit for implementing something like datashader.

---

<div class="post-metadata">

### Author: ![Bryan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bryan/32/9399_2.png) [@Bryan](https://discourse.julialang.org/u/Bryan)
#### Post date: [February 24, 2019, 7:14pm UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/16 "2019-02-24T19:14:01Z")

</div>

I’m the project lead for Bokeh. I’d just like to reiterate that I think Bokeh and Julia would make a fantastic combination. I don’t have the experience to design or implement Julia APIs myself, but I’d be more than happy to help/collaborate with anyone on the Julia side that wanted to work on Julia bindings for BokehJS (basically: generate the right pile of JSON to drive BokehJS)

---

<div class="post-metadata">

### Author: ![davidanthoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/davidanthoff/32/223493_2.png) [@davidanthoff](https://discourse.julialang.org/u/davidanthoff)
#### Post date: [February 24, 2019, 7:47pm UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/17 "2019-02-24T19:47:25Z")

</div>

Yes, a Bokeh package would be great! I won’t have time to do that, but if someone is picking up that project, please feel free to reach out how to handle things like MIME types, integration with [ElectronDisplay.jl](https://github.com/queryverse/ElectronDisplay.jl) and [VS Code](https://github.com/JuliaEditorSupport/julia-vscode), saving in different formats etc. I think I figured out good solutions for almost all of these for [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl), and I assume many of those tactics could easily be reused for a bokeh package. And I had _a lot_ of false starts on that front, so if I can help someone else avoid making those, I’d love to do so 🙂

---

<div class="post-metadata">

### Author: ![sairus7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sairus7/32/10816_2.png) [@sairus7](https://discourse.julialang.org/u/sairus7)
#### Post date: [March 6, 2019, 9:57am UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/18 "2019-03-06T09:57:13Z")

</div>

Some of the questions, that should be clarified:

1. How data sourse connection is done? Convertion to plain text (as JSON) is inefficient, one wants to pass some AbstractArray or SubArray types directly to plotting system.
2. Filters and other callbacks? Filtering functions usually are very domain-specific and should be programmed separately and bound as callbacks, just like GUI interactions, (not just declaring the standard filtering options in VegaLite).

---

<div class="post-metadata">

### Author: ![Bryan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bryan/32/9399_2.png) [@Bryan](https://discourse.julialang.org/u/Bryan)
#### Post date: [July 18, 2019, 7:34am UTC](https://discourse.julialang.org/t/interactive-plot-acting-as-a-range-slider-tool-for-another-plot/20392/19 "2019-07-18T07:34:27Z")

</div>

> 1. How data sourse connection is done? Convertion to plain text (as JSON) is inefficient, one wants to pass some AbstractArray or SubArray types directly to plotting system.

The Python Bokeh server has a websocket protocol that can send array that correspond to JS typed array types directly without any encoding. A small subset of of Bokeh server capability could be implemented in Julia, to send data in this efficient manner. If you are generating standalone output (i.e. and static HTML document) then this is obviously not an option, regardless. A base64 enocoding can be used in this case, which can be more performant than a JSON encoding, especially in the case of multi-dimensional arrays.

> Filters and other callbacks?

Bokeh supports defining Custom JS callbacks for any kind of output, and in response to any property change or update. The Python bokeh server allows real Python callbacks to be defined in reponse to these same set of events. To support Julia callbacks would mean implementing more of the Bokeh server in Julia directly, which is not a trivial task but also not an impossible task.
