Detroit Live’s documentation!

detroit-live is based on detroit and aims to bring interactivity to visualizations.

Installation

pip install detroit_live

Getting starting

If you are not familiar with detroit, please have a look at the detroit’s documentation.

In detroit_live, Selection becomes LiveSelection. A LiveSelection has the distinctive feature to share data, event listeners and event producers without explicit code.

To add interactivity to your visualization, there are two ways:

Listener callbacks

Listener callbacks are attached to selected nodes. They are defined as functions which take three parameters and return nothing:

  • event (Event) - Event received by the websocket. Most of the time, this event is a MouseEvent. See event types for predefined events.

  • d (Any | None) - The data associated to the selected node

  • node (lxml.etree.Element) - The selected node which has the event listener

For example, in the example heatmap, you must create listener callbacks when the mouse hovers an rectangle:

# <div> added in <body>
tooltip = body.append("div").attr("class", "tooltip")

# Listener callback
def mouseover(event, d, node):
    tooltip.style("opacity", 1)
    d3.select(node).style("stroke", "black").style("opacity", 1)

Here, there are two nodes which are updated : node from mouseover function and tooltip (global variable).

To create an event listener, you must call LiveSelection.on:

svg.on("mouseover", mouseover, extra_nodes=[tooltip.node()])
# or extra_nodes = tooltip.nodes()

The parameter extra_nodes must be filled when there are additional nodes to update apart from the selected node node (in this example, node != tooltip). Mouse events will be propagated into this function and only attribute changes are updated. In some cases, you want to update the inner HTML (or the text content of the element), you must fill the parameter html_nodes:

svg.on(
  "mouseover",
  mouseover,
  extra_nodes=[tooltip.node()],
  html_nodes=[tooltip.node()],
)

By default, only attributes are updated (i.e. node.attrib). However, for performance reasons, inner HTML or text content are not automatically updated.

Producer callbacks

Producers callbacks are functions called into infinite loop packed into asynchronous task. They are independant to selected nodes, and instead, you must specify which nodes must be updated by using the parameters updated_nodes and html_nodes like for event listeners.

Producer callbacks must have two arguments and returns nothing:

  • elapsed (float) - The elapsed time since the timer started in milliseconds

  • timer_event (TimerEvent) - A timer event which when it is set (by using timer_event.set()), it stops the event producers.

Here is an example when you want to update:

date = 1800

# Producer callback
def update_date(elapsed, timer_event):
     global date
     if date == 2005:
         # Stop the timer
         timer_event.set()
         return

     date += 1
     current_data = data_at(datetime(date, 1, 1))
     (
         circle.data(current_data, lambda d: d.name)
         .attr("cx", lambda d: x(d.income))
         .attr("cy", lambda d: y(d.life_expectancy))
         .attr("r", lambda d: radius(d.population))
     )
     span.text(f"Year: {date}")

event_producers = d3.event_producers()
timer_modifier = event_producers.add_interval(
    update_date,
    updated_nodes=circle.nodes() + span.nodes(),
    html_nodes=span.nodes(),
    delay=50, # milliseconds
)

# timer_modifier.restart() to restart the timer
# timer_modifier.stop() to stop the timer

In the function update_date, circle and span nodes are updated. The parameter updated_nodes must be filled in in order to send updates through websocket. Also, in updated_date function, the text content of span nodes is updated. Like event listeners, you must indicate it by filling the html_nodes parameter.

Run the application

Once you have added all necessary event listeners and event producers, you can start a web application to get interactivity by using LiveSelection.create_app:

svg.create_app().run()

Default host is localhost and default port is 5000. You can open the web application in your browser at localhost:5000.

Table of Content