Overview Examples API Source

API Reference

Boards

tnt.board creates a new track-based visualisation. Typically, each track displays a set of elements defined during its setup. Boards can be panned or zoomed within their defined limits. Once a board is created new tracks can be attached to it using the method board.add_track

Each new track needs to know how to get the data to display (either synchonously or asynchronously). A new call to get new data is performed everytime the board changes its state (while panning / zooming or programmatically). Each track should also define how to represent each of the features to display. TnT offers predefined common displays (like rectangles, lines, areas, pins) ready to use. New displays can also be created using display interface. Composite displays (ie, displays made of combinations fo different simple displays) are also allowed and a very powerful tool for displaying complex data. Examples of how to create different visualizations can be seen in the examples page.

  var myBoard = tnt.board()
      .from(0)
      .to(500)
      .min(0)
      .max(1000);

  var axisTrack = tnt.board.track()
      .height(20)
      .color("white")
      .display(tnt.board.track.feature.axis())
      .orientation("top");

  var blockTrack = tnt.board.track()
      .height(30)
      .color("#FFCFDD")
      .data (tnt.board.track.data.sync()
          .retriever(function () {
              return [{
                  start : 200,
                  end : 350
              }];
          })
      )
      .display(tnt.board.track.feature.block()
          .color("blue")
          .index(function (d) {
              return d.start;
          })
      );

  // Attach the tracks to the board (order matters)
  myBoard
      .add_track(location_track)
      .add_track(block_track);

  // Initialise the board
  myBoard(document.getElementById("mydiv"));

  // Start the board
  myBoard.start();
  

The above example starts by defining a board that displays data from position 0 to 500, being the limits of the board 0 (the default) and 1000. Then two tracks are defined. The first one is a location track with top orientation. The second track is 30 pixels high and displays one block from position 200 to 350 in the board. Both tracks are attached to the board. The board itself is a function that when executed initialises the visualisation using the provided DOM element as its container. Finally, the board is started, which means that the data is retrieved and displayed. It is important to understand and remember these three states of the visualisation:

#Board

Boards are track-based visualizations that can be panned and zoomed making all the tracks in the board to update accordingly. TnT Board can be configured using several methods that affect all the tracks in the board (like the width of the board). The height of the board is defined by the sum of the heights of all the tracks. The board can be configured using the methods explained below. When used as setters, these methods return the board object itself allowing to chain them as in this example:

// Definition
var myBoard = tnt.board()
    .from(0)
    .to(1000)
    .max(1000)
    .width(800);

myBoard
    .add_track(track1)
    .add_track(track2);

// Initialisation
myBoard(div);

// Start
myBoard.start();

      

# tnt.board ()

Creates a new track-based board visualization that can be configured using the methods explained below. The returned object is also a function that can be called passing a DOM element as its argument. This DOM element is used as a container for the visualization.

var myBoard = tnt.board()

         

# board.from (<integer>)

Defines the left coordinate of the board (the start left position). If called without arguments returns the current value.

var myBoard = tnt.board()
    .from(20);

         

# tnt.board.to (<integer>)

Defines the right coordinate of the board (the start right position). If called without arguments returns the current value.

var myBoard = tnt.board()
    .to(1000);

         

# board.min (<integer>)

Defines the minimum possible coordinate of the board. If called without arguments returns the current limit. By default this value is 0.

var myBoard = tnt.board()
    .min(100);

         

# board.max (<integer>)

Defines the upper limit (ie, the maximum possible coordinate) of the board. If called without arguments returns the current upper limit.

var myBoard = tnt.board()
    .max(1000);

         

# board.zoom_out (<integer>)

Defines the maximum extent of the board (ie, the limit when zooming out). If called without arguments returns the current value. This limit is respected even if the from and to coordinates specify spans beyond this limit. In that case, the coordinates are adjusted to satisfy this value.

// (to - from) can't be greater than 500
var myBoard = tnt.board()
    .zoom_out(500);

         

# board.zoom_in (<integer>)

Defines the minimum extent of the board (ie, the limit when zooming in). If called without arguments returns the current value. This limit is respected even if the from and to coordinates specify spans beyond this limit. In that case, the coordinates are adjusted to satisfy this value.

// (to - from) can't be lower than 100
var myBoard = tnt.board()
    .zoom_in(100);

         

# board.start ()

Starts the visualisation (re-)initialisig all the tracks feeding the tracks with their data and displays. If the board has already started re-initialises the tracks in the board to their current state.

var myBoard = tnt.board()
    .from(0)
    .to(1000)
    .min(0)
    .max(1000);

// ... Adding tracks ...
myBoard
    .add_track (track1)
    .add_track (track2);

// Initialise the board
myBoard.start();

         

# board.scroll (<float>)

Scrolls the board programmatically. The argument indicates the number of board pages to scroll, if it is possitive the board scrolls to the right, while if it is negative scrolls to the left. For example, board.scroll(1) scrolls right to the next non-overlapping page, while board.scroll(-0.5) scrolls left overlapping half a page.

var myBoard = tnt.board()
    .from(0)
    .to(1000)
    .max(1000);

myBoard(div);
myBoard.start();
myBoard.scroll(-1);

         

# board.zoom (<float>)

Zooms in/out the track the specified amount. The argument indicates the number of pages to zoom, or in other words, times of extent. For example, board.zoom(1) does not do anything, board.zoom(0.5) zooms out to double the extent and board.zoom(2) zooms in to half the extent.

var myBoard = tnt.board()
    .from(0)
    .to(1000)
    .max(1000);

    myBoard(div);
    myBoard.start();
    myBoard.zoom(2);

         

# board.tracks (<array>)

Reorders the tracks in the board. Expects an array of tracks as argument. This method requires the visualisation to have started already. The tracks are re-arranged with the order given in the array. New tracks are created while existing tracks not in the array are removed. As a side effect, the height for each existing track is recalculated. If no argument is provided, returns an array containing the current tracks in the board.

// Reorder the tracks. First tracks is put last
var tracks = myBoard.tracks();
var new_tracks = [];
new_tracks.push(tracks[0]);
new_tracks.push(tracks[2]);
new_tracks.push(tracks[1]);

myBoard.tracks(new_tracks);

         

# board.add_track (<tnt.board.track>)

Adds a new track to the track visualisation. The order in which this method is called determines the order of the tracks in the board

var myBoard = tnt.board()
    .add_track(track1)
    .add_track(track2);

         

# board.width (<integer>)

Specifies the width of the board. If the width changes after the visualisation has been initialised, the board and all the tracks are re-initialised with the new width. If no argument is provided, the current width is returned.

var myBoard = tnt.board()
    .width (800);

         

# board.allow_drag (<boolean>)

Specifies if the board can be scrolled with the mouse. If set to false, no drag event is used in the board. This method can be set dynamically after the visualisation has started. Disable dragging doesn't disallow scrolling programmatically via board.scroll.

var myBoard = tnt.board()
    .allow_drag = false;

         

# board.find_track (<string>)

Finds a track by ID. It expects the ID of the track as its argument.

var myBoard = tnt.board()
    .from(0)
    .to(1000);

var myTrack = tnt.board.track()
    .display(...)
    .data(...)
    .id("mytrack");

var t = myBoard.find_track("mytrack");

         

#Track

Each board can contain one of more tracks to display data. They are piled up in the board vertically (growing downwards) in the order of attachment to the board. Tracks are created using the constructor tnt.board.track and attached using board.add_track. Each track instance can be configured using the methods explained below. When used as setters, these methods return the track object allowing to chain them as in the following example:

var myBoard = tnt.board()
    .from(0)
    .to(500)
    .min(0)
    .max(500);

var locationTrack = tnt.board.track()
    .height(20)
    .color("white")
    .display (tnt.board.track.feature.axis()
        .orientation("top");
    );

var blockTrack = tnt.board.track()
    .height(30)
    .color("#FFCFDD")
    .data (tnt.board.track.data.sync()
        .retriever (function () {
            return [{
                start : 200,
                end : 350
            }];
        })
    );

myBoard
    .add_track (locationTrack)
    .add_track (blockTrack)

      

# tnt.board.track ()

Creates a new track. This track has to be configured via its methods. The newly created track can be attached to the board using board's add_track method.

var myBoard = tnt.board().from(0).to(500).max(500);

var blockTrack = tnt.board.track()
    .height(30)
    .color("#FFCFDD")
    .data (tnt.board.track.data.sync()
    .retriever(function () {
        return [{
            start : 200,
            end : 350
        }];
    })
);

         

# track.scale ()

Returns the scale to transform between the input domain and the output range. This scale is needed when elements (specified in the user-space) are displayed in the track (pixels-space). See the display interface for an example of use.

var scale = myTrack.scale();

         

# track.color (<string>)

Specifies the background color of the track. Color names ("white") and hexadecimal codes ("#FFFFFF") are allowed. If called without arguments, the current track color is returned.

var blockTrack = tnt.board.track()
    .color("#FFCFDD");

         

# track.height (<integer>)

Defines the height of the track in pixels. If called without arguments, returns the current height. This value can be changed after the visualisation has started, but for the change to be applied to the track, the board.tracks method should be called.

var myBoard = tnt.board();
var blockTrack = tnt.board.track()
    .height(30);

         

# track.label (<string>)

Sets a label to the track. This label is displayed in the top left corner of the track.

var block_track = tnt.board.track()
    .label("My Data");

         

# track.id (<string>)

Sets an ID for the track. Uniqueness of track IDs is required in order to avoid unexpected results. Any track missing an ID when the tracks are initialised are assigned a numerical ID starting with "1". This means that explicitely giving low numerical IDs to tracks is not recommended to avoid ID collisions. If called without arguments, returns the current ID of the track.

var track = tnt.board.track()
    .data(...)
    .display(...)
    .id("mytrack");

var trackID = track.id(); // "mytrack"

         

#Data

Tracks need data to display. TnT Board provides two generic methods to fetch it: tnt.board.track.data.sync, which pulls data into the track synchronously and tnt.board.track.data.async, which relies on ES2015 Promises to fetch the data asynchronously. Both methods offer the same interface and share the same configuration methods.

var dataSync = tnt.board.track.data.sync()
     .retriever (function () {
         return [
             {
                 start : 200,
                 end   : 350
             }
         ];
     });

// Assumes that a Promise library is available
 var dataAsync = tnt.board.track.data.async()
     .retriever (function () {
         return new Promise (function (resolve, reject) {
             resolve ([
                 {
                     start : 200,
                     end : 350
                 }
             ])
         });
     });

 var track1 = tnt.board.track()
     .data(dataSync);

 var track2 = tnt.board.track()
     .data(dataAsync);

      

# track.data (<tnt.board.track.data>)

Specifies a new data retriever for the track. This is used on every board update to retrieve new data to display

var track = tnt.board.track()
    .data (data);

         

# tnt.board.track.data.sync ()

Specifies a synchronous data retriever.

var dataSync = tnt.board.track.data.sync()
    .retriever (function () {
        return [
            {
                start : 200,
                end   : 350
            }
        ];
    });

         

# tnt.board.track.data.async ()

Specifies an asynchronous data retriever.

// Assumes that a Promise library is available
var dataAsync = tnt.board.track.data.async()
    .retriever (function () {
        return new Promise (function (resolve, reject) {
            resolve ([
                {
                    start : 200,
                    end : 350
                }
            ])
        });
    });

         

# tnt.board.track.data.empty ()

Convenience data element for tracks that doesn't require data. It is based on the synchronous data retriever so it still supports the same methods.

var track = tnt.board.track()
    .data(tnt.board.track.data.empty());

         

# data.retriever (<callback>)

Sets a callback that retrieves the data to visualise in the track. This callback is called passing the location object as its argument to allow positional data retrievals. This location object has the from and to properties. Inside of the callback, this is set to the current track. The callback is expected to return an array of objects (if the data is sync) or a Promise that resolves to an array of objects (if the data is async). These returned objects represent the elements to be displayed in each update of the board

var dataSync = tnt.board.track.data.sync()
    .retriever (function () {
        return [
            {
                start : 200,
                end   : 350
            }
        ];
    });

         

# data.elements ()

Returns the elements that resulted from the last retrieval. Normally, there is no need to call this method directly since it is called implicitely by the display of the visualisation. It is useful though if the data needs to be edited before being passed to the Display

var elems = dataSync.elements();

         

#Display

Once a track has retrieved its data, it needs to display it. TnT Board provides several ready-to-use data displays that can be ready-to-use by the tracks (see for example tnt.board.track.feature.block or tnt.board.track.feature.pin). These ready-to-use displays are based on the generic display interface and hence expose all the methods described for the generic interface. Creating custom features is also possble using the generic interface.

Each display is composed of one or more visual features. A display with more that one feature can be used to display different types of data in the same track (see tnt.board.track.feature.), for an example).

var axis_track = tnt.board.track()
    .height(20)
    .color("white")
    .display(tnt.board.track.feature.axis()
        .orientation("top")
    );

var block_track = tnt.board.track()
    .height(30)
    .color("#FFCFDD")
    .data (tnt.board.track.data.sync()
        .retriever (function () {
            return [
                {
                    start : 200,
                    end   : 350
                }
            ];
        })
    )
    .display(tnt.board.track.feature.block()
        .color("blue")
    );

      

# track.display (<tnt.board.track.feature>)

Specifies a new data display for the track. This is used everytime new update is made in the track. If called without arguments, the current display is returned.

var track = tnt.board.track()
    .display (tnt.board.track.feature.block());

         

# [interface] tnt.board.track.feature ()

General interface for creating visual displays of data. This interface exposes four methods to configure the feature, create, mover, distribute and fixed. These methods are called interface methods and can be used to create new displays.

To understand how to use these interface methods it is useful to understand the interaction model in TnT Board:

  1. When the board is started all the tracks are cleaned using the reset method
  2. All the tracks are then updated. This makes new data to be retrieved based on the current coordinates of the board
  3. The update method of the display is called once the new data is available. This method calls the distribute interface method in case some vertical distribution needs to be done (for example, avoiding overlaps between elements) and finally renders the elements based on the create interface method
  4. While the board is panned or zommed the display executes the move interface method
  5. When the the interaction stops new data is retrieved again using the new board's coordinates, the distribute method is called again on all the elements and the create method only on the new ones.

TnT Board also offers several ready-to-use displays built on top of this general interface and described below.
The interface also exposes several methods that are inherited by the ready-to-use displays.

var vertical_line = tnt.board.track.feature()
    .create (function (new_elems) {
        var track = this;
        var xScale = track.scale();
        new_elems
            .append("line")
            .attr("x1", function (d) {
                return xScale(d.pos);
            })
            .attr("x2", function (d) {
                return xScale(pos.d);
            })
            .attr("y1", 0)
            .attr("y2", track.height())
            .attr("stroke", feature.color());
    })
    .move (function (vlines) {
        select("line")
            .attr("x1", function (d) {
                return xScale(d.pos);
            })
            .attr("x2", function (d) {
                return xScale(d.pos);
            })
    });

var board = tnt.board()
    .data (...)
    .display (vertical_line);

         

# [interface method] feature.create (<callback>)

Specifies how new elements are rendered. Accepts a callback that is called with a d3 selection containing the new elements on every data update. Inside of this function, this is set to the current track. When this method is called without arguments returns the current value.

var feature = tnt.board.track.feature()
    .create (function (new_elems) {
        var track = this;
        var xScale = track.scale();
        new_elems
            .append("line")
            .attr("x1", function (d) {
                return xScale(d.pos);
            })
            .attr("x2", function (d) {
                return xScale(pos.d);
            })
            .attr("y1", 0)
            .attr("y2", track.height())
            .attr("stroke", feature.color());
    });

         

# [interface method] feature.distribute (<callback>)

Distributes the elements to display in the track. Accepts a callback that is called with a d3 selection containing the elements displayed in the track. Inside the callback, this is set to the current track. When called without arguments this method returns the current value.

var feature = tnt.board.track.feature()
    .distribute (function (sel) {
        sel
            .select("rect")
            .transition()
            .duration(500)
            .attr("y", function (d) {
                return (feature.layout().gene_slot().slot_height * d.slot);
            })
            .attr("height", feature.layout().gene_slot().gene_height);
    })

         

# [interface method] feature.move (<callback>)

Specifies how the existing elements are moved when the board is panned or zoomed. Accepts a callback that is called with a the d3 selection containing the current elements in the track. Inside of the callback, this is set to the current track. When called without arguments this method returns the current value.

# [interface method] feature.fixed (<callback>)

Sets a callback to display non-scaled elements in the display. There are cases where the track needs to dispay non-scaled visual elements (fixed while panning or zomming) like rulers, baselines, etc. The method specified with this callback is called on display initialisation passing the board's width as its argument. In this function, this is set to the current track. When called without arguments this method return the current guider function.

# feature.update ()

Updates the track with the current data elements. This is called automatically with every data update but can be called at any point. This is useful to update manually a track individually. This method expects to have this set to the track it belongs to.

# feature.reset ()

Resets the visualisation of a track. This method expects to have this set to the track it belongs to. In the resetting process all the SVG elements with classes tnt_elem, tnt_guider and tnt_guider are removed.

# feature.index (<callback>)

Specifies an index function to link elements between successive track updates. When a track is updated and the new data is retrieved, the display needs to know which elements are new, which have dissapeared and which are currently in the display. This binding of elements is made before the new data is displayed and is based on this function. This function is called on every (new & old) element passing the elements as its argument. Elements for which the index function returns the same value are linked or bound together. By default data are linked based on their position in the data array.

// Data track
var pin_track = tnt.board.track()
    .height(60)
    .color("white")
    .display (tnt.board.track.feature.pin()
        // Elements differentiate from one another based on their pos property
        .index (function (d) {
            return d.pos;
        })
        .domain([0.3, 1.2])
        .color("red")
    )
    .data (tnt.board.track.data.sync()
        retriever (function (loc) {
            var elems = [];
            var data = pins_data;
            for (var i=0; i<data.length; i++) {
                if ((data[i].pos > loc.from) && (data[i].pos < loc.to)) {
                    elems.push(data[i]);
                }
            }
            return elems;
        })
    );

         

# display.color (<string>)

Specifies the foreground color of the elements to display in the track. Color names ("red") and hexadecimal codes ("00FF00") are allowed. If called without arguments, the current color is returned. By default all elements are black.

var display = tnt.board.track.feature()
    .color("red");

         

# tnt.board.track.feature.location ()

Creates a new location feature for a track. This is a data-less display that shows the current range of the board in the track

var location_track = tnt.board.track()
    .color("white")
    .display(tnt.board.track.feature.location());

         

# tnt.board.track.feature.axis ()

Creates a new axis feature for a track. This is a data-less display that shows the x-axis of the plot in the track

var axis_track = tnt.board.track()
    .height(20)
    .color("white")
    .display(tnt.board.track.feature.axis()
        .orientation("top")
    );

         

# axis.orientation (<string>)

Sets the orientation of a tnt.board.track.feature.axis feature. It accepts a string as argument that can be either "top" or "bottom"

# tnt.board.track.feature.block ()

Creates a new block-based feature for a track. This feature expects the data as an array of objects containing numerical start and end properties, although the name of the properties is configurable.

var block_track = tnt.board.track()
    .height(30)
    .color("#FFCFDD")
    .data (tnt.board.track.data.sync()
        .retriever (function () {
            return [
                {
                    start : 200,
                    end   : 350
                }
            ];
        })
    )
    .display(tnt.board.track.feature.block()
        .color("blue")
    );

         

# tnt.board.track.feature.pin ()

Creates a new pin-based feature for a track. This feature expects the data as an array of objects containing numerical pos and val properties, although the name of the properties is configurable. The pos property refers to its x-position in the track and the val property refers to the height of the pin in the track and expects a number in the y domain (by default, between 0 and 1).

var pin_track = tnt.board.track()
    .display (tnt.board.track.feature.pin())
    .data (tnt.board.track.data.sync()
        .retriever (function () {
            return [
                {pos : 200, val: 0.5},
                {pos : 355, val: 0.8}
            ];
        })
    );

         

# pin.domain (<array>)

Sets the domain for the y-axis in the tnt.board.track.feature.pins feature. It expects an array of numerical values representing the lower and upper limit respectively for the y-axis. By default the domain is [0,1]. Called without arguments return the current domain.

var pin_track = tnt.board.track()
    .display (tnt.board.trac.feature.pin()
        .domain([0.3, 1.2])
    )
    .data (tnt.board.track.data.sync()
        .retriever (function () {
            return [
                {pos : 200, val: 0.5},
                {pos : 355, val: 0.8}
            ];
        })
    );

         

# tnt.board.track.feature.line ()

Creates a new line-based feature for a track. The line is defined by a series of points in the track. This points are applied a tension to smooth the connections between the points. This feature expects the data as an array of objects containing numerical pos and val properties, although the name of the properties is configurable. The pos property refers to the x-position of each point in the track and the val property refers to the height of the points in the track and expects a number in the y-axis domain (by default, between 0 and 1).

var line_track = tnt.board.track()
    .display (tnt.board.trac.feature.line())
    .data (tnt.board.track.data.sync()
        .retriever (function () {
            return [
                {pos : 200, val: 0.5},
                {pos : 355, val: 0.8}
                // ...
            ];
        })
    );

         

# tnt.board.track.feature.area ()

Creates a new area-based feature for a track. This feature is based on the tnt.board.track.feature.line feature but coloring the area behind the curve.

var line_track = tnt.board.track()
    .display (tnt.board.track.feature.area())
    .data (tnt.board.track.data.sync()
        .retriever (function () {
            return [
                {pos : 200, val: 0.5},
                {pos : 355, val: 0.8}
                // ...
            ];
        })
    );

         

# tnt.board.track.feature.vline ()

Creates a feature that displays vertical lines in the specified positions. It expects an array of objects having a field representing the x-coordinate of the lines in the track. This value is the same one specified in the index property of the display

var vlines_track = tnt.board.track()
    .display (tnt.board.track.feature.vline())
    .data (tnt.board.track.data.sync(
        .index (function (d) {
            return d.pos;
        })
        .retriever (function () {
            return [{pos: 15}, {pos: 30}, {pos: 100}];
        })
    ));

         
Fork me on GitHub