Reactive Vega A Streaming Dataflow Architecture for Declarative Interactive Visualization Arvind Satyanarayan, Ryan Russell, Jane Hoffswell, Jeffrey Heer Presented by Zipeng Liu Dec 3 2015 CSPSC 547 Information Visualization Based on Arvind’s slides presented in InfoVis’15. http://arvindsatya.com/slides/ReactiveVega-InfoVis2015.pdf
Reactive Vega
“Talk is cheap. Show me the code” –Linus Torvalds 3
{ "width": 650, "height": 300, "data": [ {"name": "stocks", "url": “data/stocks.json”} ], "scales": [{ "name": "sx", "type": "ordinal", "domain": {"data": "stocks", "field": "date"} "range": "width" }, ... ], "axes": [ {"type": "x", "scale": "sx"}, ... ], "marks": [{ "type": "group", "from": { "data": "stocks", "transform": [ {"type": "facet", "groupby": ["symbol"]} ] }, "marks": [{ "type": "line", "properties": { "enter": { "x": {"scale": "sx", "field": "date"}, "y": {"scale": "sy", "field": "price"}, "stroke": {"scale": "sc", "field": "symbol"} }} }, { "type": "text",... }] 4
{ "width": 650, "height": 300, Data + "data": [ {"name": "stocks", "url": “data/stocks.json”} Transforms ], "scales": [{ "name": "sx", "type": "ordinal", "domain": {"data": "stocks", "field": "date"} "range": "width" }, ... ], "axes": [ {"type": "x", "scale": "sx"}, ... ], "marks": [{ "type": "group", "from": { "data": "stocks", "transform": [ {"type": "facet", "groupby": ["symbol"]} ] }, "marks": [{ "type": "line", "properties": { "enter": { "x": {"scale": "sx", "field": "date"}, "y": {"scale": "sy", "field": "price"}, "stroke": {"scale": "sc", "field": "symbol"} }} }, { "type": "text",... }] 5
{ "width": 650, "height": 300, Data + "data": [ {"name": "stocks", "url": “data/stocks.json”} Transforms ], "scales": [{ "name": "sx", "type": "ordinal", Scales "domain": {"data": "stocks", "field": "date"} "range": "width" }, ... ], "axes": [ {"type": "x", "scale": "sx"}, ... ], "marks": [{ "type": "group", "from": { "data": "stocks", "transform": [ {"type": "facet", "groupby": ["symbol"]} ] }, "marks": [{ "type": "line", "properties": { "enter": { "x": {"scale": "sx", "field": "date"}, "y": {"scale": "sy", "field": "price"}, "stroke": {"scale": "sc", "field": "symbol"} }} }, { "type": "text",... }] 6
{ "width": 650, "height": 300, Data + "data": [ {"name": "stocks", "url": “data/stocks.json”} Transforms ], "scales": [{ "name": "sx", "type": "ordinal", Scales "domain": {"data": "stocks", "field": "date"} "range": "width" }, ... ], "axes": [ Guides {"type": "x", "scale": "sx"}, ... ], "marks": [{ "type": "group", "from": { "data": "stocks", "transform": [ {"type": "facet", "groupby": ["symbol"]} ] }, "marks": [{ "type": "line", "properties": { "enter": { "x": {"scale": "sx", "field": "date"}, "y": {"scale": "sy", "field": "price"}, "stroke": {"scale": "sc", "field": "symbol"} }} }, { "type": "text",... }] 7
{ "width": 650, "height": 300, Data + "data": [ {"name": "stocks", "url": “data/stocks.json”} Transforms ], "scales": [{ "name": "sx", "type": "ordinal", Scales "domain": {"data": "stocks", "field": "date"} "range": "width" }, ... ], "axes": [ Guides {"type": "x", "scale": "sx"}, ... ], "marks": [{ "type": "group", "from": { "data": "stocks", "transform": [ {"type": "facet", "groupby": ["symbol"]} ] }, "marks": [{ Marks "type": "line", "properties": { "enter": { "x": {"scale": "sx", "field": "date"}, "y": {"scale": "sy", "field": "price"}, "stroke": {"scale": "sc", "field": "symbol"} }} }, { "type": "text",... }] 8
Why Declarative • Less code + faster iteration • Performance + scalability • Reuse + portability (flexibility) • Programmatic generation 9
Interaction?
Reactive Vega
Imperative Interaction var dragging = false; d3.selectAll(“rect") .on("mousedown", function() { Manually maintain state 1. dragging = true; and dependencies }) .on("mouseup", function() { dragging = false; Side-effects 2. d3.event.stopPropagation(); }) .on("mousemove", function() { “Callback hell” 3. var e = d3.event; if (!dragging) return; d3.select(this) .attr(“x”, e.pageX) .attr(“y”, e.pageY); }); 12
Declarative Interaction • Event-driven Functional Reactive Programming (E-FRP) • mutable values as time-varying data streams • event triggers propagation through dataflow graph • but only for scalar values • Streaming Database 13
Event Streams 14
Demo: SPLOM of Iris http://vega.github.io/vega-editor/index.html?spec=linking
mousedown (x, y) Start Offset Selection event.target Cell Predicate x start ≤ x pt ≤ x end && y start ≤ y pt ≤ y end Offset [mousedown, mouseup] > *:mouseup mousemove (x, y) End 19 16
mousedown (x, y) Start Scale Inversion Offset Query event.target Cell Predicate sepal start ≤ sepal pt ≤ sepal end && petal start ≤ petal pt ≤ petal end Offset Scale Inversion [mousedown, mouseup] > *:mouseup mousemove (x, y) End 21 17
mousedown (x, y) Start Scale Inversion Offset event.target Cell Inside Brush Offset Scale Inversion [mousedown, mouseup] > *:mouseup mousemove (x, y) End 22 18
Circle Mark mousedown (x, y) Fill Rule Start species ) (Scaled if blue Inside Brush orange green Scale Inversion else Offset gray event.target Cell Inside Brush Offset Scale Inversion [mousedown, mouseup] > *:mouseup mousemove (x, y) End 23 19
Architecture: Dataflow Graph optional
Compile Time *:mousemove stocks x -1 {... "data": [... Input index {...}, {... "name": "index_pts", "source": "stocks", "transform": [{ Filter "type": "filter", "test": "month(datum) == month(index) && year(datum) == year(index)" }] Output }, {...} ]... }... 29 21
Run Time *:mousemove stocks x -1 {... "data": [... Input index {...}, {... "name": "index_pts", Status. "source": "stocks", "transform": [{ Tuples flagged as added , Filter "type": "filter", modified , or removed . "test": "month(datum) == month(index) && year(datum) == year(index)" }] Output }, {...} ]... }... 31 22
Recommend
More recommend