Behaviours

In this section, we will get an in-depth view of what behaviours are and what happens when a behaviour changes.

Behaviours are how the canvas reacts to a particular interaction. A change in behaviour is a deviation from the default view of the canvas and thus is usually accompanied by a visual change. For example, when we hover over a point in the canvas, we change the behaviour of the canvas by highlighting the point ( thereby getting a tooltip). This happens because the behaviour of the chart has changed from the default rendered view to the highlighted view.

Let's try and understand how this works with the simple cars.json data.

How does a behaviour change?

There are two ways to change the behaviour of the canvas :

  • Interacting with a chart: When we interact with the chart, it causes a physical action to be triggered which changes the behaviour(s) attached to it
  • Dispatching a behaviour dynamically: We can dynamically dispatch a behaviour with the required payloads, which can cause the behaviour to change. Dispatching behaviours are found here.

Understanding the change in behaviour

In order to change the behaviour(either by a physical action or dynamically), it has to be dispatched with a payload containing the criteria for the behaviour. The payload looks like this:

payload: {
        criteria: {
            Origin: ['Japan'],
            Cylinders: [3, 6, 8]
        }
    }

Once the behaviour gets the payload, it searches for all the rows in the associated DataModel and identifies the rows that satisfy the criteria for the behaviour.

The rows that satisfy the criteria together comprise the selection set. The rows that do not satisfy the criteria together comprise the rejection set.

These two sets form the basis of all kind of the output of an interaction. The set of rows contained in both the sets taken together thus forms the complete set, i.e., the complete set of rows in the DataModel.

For instance, from the payload above, the set of rows which contain the Origin as Japan and the Cylinder values as 3, 6 and 8 form the selection set as is seen below:

main
run-button
run-button
reset-button
    const compose = DataModel.Operators.compose;
    const select = DataModel.Operators.select;
  
    const composer = compose(
     	select(fields=>fields.Origin.value === 'Japan' && 
             (fields.Cylinders.value ==='3' 
              	|| fields.Cylinders.value ==='6' 
                || fields.Cylinders.value ==='8')
           ))

    const selectedDM = composer(dataModelInstance)

Similarly, the rejection set would contain the set of rows that do not satisfy this set:

main
run-button
run-button
reset-button
    const compose = DataModel.Operators.compose;
    const select = DataModel.Operators.select;
  
    const composer = compose(
     	select(fields=>!(fields.Origin.value === 'Japan' && 
             (fields.Cylinders.value ==='3' 
              	|| fields.Cylinders.value ==='6' 
                || fields.Cylinders.value ==='8'))
           ))


    const selectedDM = composer(dataModelInstance)

This way, every behaviour always has two sets and any action that needs to be performed after a behaviour can be applied on either of the sets based on the actual use case.

Let's understand sets a bit further with a visual example. First, let us create a scatter plot of Horsepower vs Acceleration as show below:

main
run-button
run-button
reset-button
loadData('/static/cars.json').then((res) => {    
  let node = document.getElementById('chart-container');    
  const env = muze();    
  const canvas = env.canvas();    
  const DataModel = muze.DataModel;  	
  loadData('/static/cars-schema.json').then((schema) => {
    const dataModelInstance = new DataModel(res, schema);
          canvas
          	.width(600)
          	.height(400)
			.rows(['Horsepower'])
			.columns(['Acceleration'])
    		.detail(['Name'])
			.data(dataModelInstance)
    		.mount(node)
    });
})

Every time we drag in the chart, we see a selection box being drawn. Any set of circles inside the box are highlighted while the others fade out:

alt text

The circles that are enclosed within the box are part of the selection set, while the ones outside are part of the rejection sets.

How did that rectangular box appear when we dragged? That's a sideeffect of the behaviour. You can also choose to have a different visual interpretation of this physical action using sideeffects(which you can read about here).

Each set can be affected varyingly as per the choice of the interaction. And since every behaviour can be configured to have their own side effects, you can customize virtually any part of the chart you want.

The goal of the behaviours are to manage the selection and rejection sets which are then propagated to the respective DataModels. Once the propagation occurs, each canvas individually reacts based on that propagation. The sideeffects are also caused due to that propagation.

Let us understand the types of selection and rejection sets.

Types of selection and rejection sets

There are multiple types of selection and rejection sets and you can use all of these sets to get the sort of interactions you desire from the canvas.

Let us look into all the sets:

Types of selections sets:

There are two types of selection sets : New Entry Set and Old Entry Set. In order to understand these sets, let's understand them with an example where we have a bar chart between Horsepower and Origin:

main
run-button
run-button
reset-button
loadData('/static/cars.json').then((res) => {    
  let node = document.getElementById('chart-container');    
  const env = muze();    
  const canvas = env.canvas();    
  const DataModel = muze.DataModel;  	
  loadData('/static/cars-schema.json').then((schema) => {
    const dataModelInstance = new DataModel(res, schema);
          canvas
          	.width(600)
          	.height(400)
			.rows(['Horsepower'])
			.columns(['Origin'])
			.data(dataModelInstance)
    		.mount(node)
    });
})

Now when we click on a bar, we get the following interaction:

alt text

As we know, in the above interaction, the rows in the DataModel that uniquely identify rows for the Origin value of USA form the selection set.

Before interacting with the canvas, the selection set was empty. On clicking the bar, a new entry has been made to the set. Hence, every time we interact with the chart and a new entry is made to the selection set, it becomes a part of the New Entry Set.

Thus, the rows for USA in the above example are part of the New Entry Set.

On clicking on another bar in the chart, we get the following interaction:

alt text

As we can see, this time the selection set consists of the rows for the Origin values of USA and Europe. Before this interaction, the selection set was not empty, but contained the set of rows for USA.

Hence, the new entries only count for the rows for the Origin value of Europe. Thus, in this interaction, all of the rows satisfying Origin value of Europe are a part of the New Entry Set. Consequently, the set of rows which were present in the selection set before interaction(those for USA) are the old entries for that set and hence are a part of the Old Entry Set.

Therefore, the selection set consists of all the rows present in the New Entry Set and the Old Entry Set.

To recapitulate:

  • New Entry Set: consists of the rows that have been currently interacted with and are not already a part of the selection set
  • Old Entry Set: consists of the rows already present in the selection set which satisfy the condition for selection

To note, you can customize your behaviours to either retain rows from the Old Entry Set or remove them for every interaction. This can give you two different kinds of reactions(Read Volatile and Persistent Behaviours.

Types of rejection sets

As there are two types of selection sets, similarly there are two types of rejection sets as well : New Exit Set and Old Exit Set. In order to understand these sets, let's understand them with the previous example where we have a bar chart between Horsepower and Origin. When we first click on a bar, we get the following interaction:

alt text

As we know, in the above interaction, the rows in the DataModel that uniquely identify rows for the Origin value of USA form the selection set. Thus, the set of rows not satisfying this condition form the rejection set.

Before interacting with the canvas, the rejection set is empty. On clicking the bar, the rows not satisfying Origin value of USA are the new entries in the rejection set and the make up the New Exit Set. Thus, everytime an interaction occurs, the new set of entries in the rejection set constitute the New Exit Set.

On clicking on another bar in the chart, we get the following interaction:

alt text

As we can see, this time the rejection set consists of the rows nor satisfying the condition for the Origin values of USA and Europe. Before this interaction, the rejection set was not empty, but contained the set of rows for Japan and Europe.

Hence, there are no new entries in the rejection set. Rather the set for the Origin - Europe is removed from this set and so the New Exit Set will be empty in this case.

Consequently, the set of rows which were present in the rejection set before interaction(those for Japan and Europe ) are now updated with only the old entries for Japan present and these set of rows become part of the Old Exit Set.

Therefore, the rejection set consists of all the rows present in the New Exit Set and the Old Exit Set.

To recapitulate:

  • New Exit Set: consists of the elements that are now part of the rejection set with and weren't previously a part of it.
  • Old Exit Set: stores the rejected rows prior to the current exit. If a set of rows is already in the rejection set and isn't interacted with, it will stay in the old exit set.

Volatile and Persistent Behaviours

There are two types of behaviours that are pre existing in Muze. They are only different in the way they use the selection and rejection sets and thus it is up to you to use those sets as you want.

Volatile Behaviour

A volatile behaviour is a type of behaviour that does not retain the Old Entry Set whenever the same behaviour changes. For instance, when we hover over bars in the chart, the selection set consists only of the bar currently being hovered upon. Thus, only the new entries or the New Entry Set constitute the selection set.

Persistent Behaviour

A persistent behaviour is a type of behaviour that retains the Old Entry Set whenever the same behaviour changes. For instance, when we click multiple bars in the chart, the selection set consists of all the bars that have been clicked on. Thus, both the New Entry Set and Old Entry Set constitute the selection set for every interaction.

Firebolt Manages Behavioural Action

Once the behavioural action has done creating the selection and rejection sets, Muze's Firebolt retrieves the set of rows from the Selection Set and initiates the propagation to the DataModel. This propagation is integral for the data driven interaction and we'll know more about it separately. Click here to know more about DataModel Propagation.

As mentioned earlier, each behaviour has a Side Effect mapped to it. Firebolt dispatches this Side Effect which brings about a change in the visualization. You can read more about Side Effects here.

Wrapping Up

In this section, we had an in depth idea of what behaviours are and how they work. In the future, we will learn more about how to use those rejection sets for custom interactions. To summarize:

  • Behaviours are how the canvas(es) react/act during an interaction
  • Behaviours receive a payload and create selection and rejection sets based on that from the DataModel
  • It propagates data of the selection set to the DataModel and triggers respective side effects to occur
  • There are two types of selection sets: new entry set(which stores the new entries in the selection) and the old entry set(which stores the already present entries in the selection set)
  • There are also two types of rejection sets: new exit set(which stores the new entries in the rejection) and the old exit set(which stores the already present entries in the rejection set)
  • There are two types of behaviours: volatile and persistent behaviours
  • Volatile Behaviours do not retain the previous selections while the persistent behaviours retain the old selections in the Old Entry Set
  • Firebolt is responsible for managing the propagation and triggering sideeffects once the selection and rejection sets have been made