GithubHelp home page GithubHelp logo

d3-chord's Introduction

d3-chord

Visualize relationships or network flow with an aesthetically-pleasing circular layout.

Chord Diagram

Installing

If you use npm, npm install d3-chord. You can also download the latest release on GitHub. For vanilla HTML in modern browsers, import d3-chord from Skypack:

<script type="module">

import {chord} from "https://cdn.skypack.dev/[email protected]";

const c = chord();

</script>

For legacy environments, you can load d3-chord’s UMD bundle from an npm-based CDN such as jsDelivr; a d3 global is exported:

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>

const chord = d3.chord();

</script>

API Reference

# d3.chord() · Source

Constructs a new chord layout with the default settings.

# chord(matrix) · Source

Computes the chord layout for the specified square matrix of size n×n, where the matrix represents the directed flow amongst a network (a complete digraph) of n nodes. The given matrix must be an array of length n, where each element matrix[i] is an array of n numbers, where each matrix[i][j] represents the flow from the ith node in the network to the jth node. Each number matrix[i][j] must be nonnegative, though it can be zero if there is no flow from node i to node j. From the Circos tableviewer example:

const matrix = [
  [11975,  5871, 8916, 2868],
  [ 1951, 10048, 2060, 6171],
  [ 8010, 16145, 8090, 8045],
  [ 1013,   990,  940, 6907]
];

The return value of chord(matrix) is an array of chords, where each chord represents the combined bidirectional flow between two nodes i and j (where i may be equal to j) and is an object with the following properties:

  • source - the source subgroup
  • target - the target subgroup

Each source and target subgroup is also an object with the following properties:

  • startAngle - the start angle in radians
  • endAngle - the end angle in radians
  • value - the flow value matrix[i][j]
  • index - the node index i

The chords are typically passed to d3.ribbon to display the network relationships. The returned array includes only chord objects for which the value matrix[i][j] or matrix[j][i] is non-zero. Furthermore, the returned array only contains unique chords: a given chord ij represents the bidirectional flow from i to j and from j to i, and does not contain a duplicate chord ji; i and j are chosen such that the chord’s source always represents the larger of matrix[i][j] and matrix[j][i].

The chords array also defines a secondary array of length n, chords.groups, where each group represents the combined outflow for node i, corresponding to the elements matrix[i][0 … n - 1], and is an object with the following properties:

  • startAngle - the start angle in radians
  • endAngle - the end angle in radians
  • value - the total outgoing flow value for node i
  • index - the node index i

The groups are typically passed to d3.arc to produce a donut chart around the circumference of the chord layout.

# chord.padAngle([angle]) · Source

If angle is specified, sets the pad angle between adjacent groups to the specified number in radians and returns this chord layout. If angle is not specified, returns the current pad angle, which defaults to zero.

# chord.sortGroups([compare]) · Source

If compare is specified, sets the group comparator to the specified function or null and returns this chord layout. If compare is not specified, returns the current group comparator, which defaults to null. If the group comparator is non-null, it is used to sort the groups by their total outflow. See also d3.ascending and d3.descending.

# chord.sortSubgroups([compare]) · Source

If compare is specified, sets the subgroup comparator to the specified function or null and returns this chord layout. If compare is not specified, returns the current subgroup comparator, which defaults to null. If the subgroup comparator is non-null, it is used to sort the subgroups corresponding to matrix[i][0 … n - 1] for a given group i by their total outflow. See also d3.ascending and d3.descending.

# chord.sortChords([compare]) · Source

If compare is specified, sets the chord comparator to the specified function or null and returns this chord layout. If compare is not specified, returns the current chord comparator, which defaults to null. If the chord comparator is non-null, it is used to sort the chords by their combined flow; this only affects the z-order of the chords. See also d3.ascending and d3.descending.

# d3.chordDirected() · Source, Examples

A chord layout for directional flows. The chord from i to j is generated from the value in matrix[i][j] only.

# d3.chordTranspose() · Source

A transposed chord layout. Useful to highlight outgoing (rather than incoming) flows.

# d3.ribbon() · Source

Creates a new ribbon generator with the default settings.

# ribbon(arguments…) · Source

Generates a ribbon for the given arguments. The arguments are arbitrary; they are simply propagated to the ribbon generator’s accessor functions along with the this object. For example, with the default settings, a chord object expected:

const ribbon = d3.ribbon();

ribbon({
  source: {startAngle: 0.7524114, endAngle: 1.1212972, radius: 240},
  target: {startAngle: 1.8617078, endAngle: 1.9842927, radius: 240}
}); // "M164.0162810494058,-175.21032946354026A240,240,0,0,1,216.1595644740915,-104.28347273835429Q0,0,229.9158815306728,68.8381247563705A240,240,0,0,1,219.77316791012538,96.43523560788266Q0,0,164.0162810494058,-175.21032946354026Z"

Or equivalently if the radius is instead defined as a constant:

const ribbon = d3.ribbon()
    .radius(240);

ribbon({
  source: {startAngle: 0.7524114, endAngle: 1.1212972},
  target: {startAngle: 1.8617078, endAngle: 1.9842927}
}); // "M164.0162810494058,-175.21032946354026A240,240,0,0,1,216.1595644740915,-104.28347273835429Q0,0,229.9158815306728,68.8381247563705A240,240,0,0,1,219.77316791012538,96.43523560788266Q0,0,164.0162810494058,-175.21032946354026Z"

If the ribbon generator has a context, then the ribbon is rendered to this context as a sequence of path method calls and this function returns void. Otherwise, a path data string is returned.

# ribbon.source([source]) · Source

If source is specified, sets the source accessor to the specified function and returns this ribbon generator. If source is not specified, returns the current source accessor, which defaults to:

function source(d) {
  return d.source;
}

# ribbon.target([target]) · Source

If target is specified, sets the target accessor to the specified function and returns this ribbon generator. If target is not specified, returns the current target accessor, which defaults to:

function target(d) {
  return d.target;
}

# ribbon.radius([radius]) · Source

If radius is specified, sets the source and target radius accessor to the specified function and returns this ribbon generator. If radius is not specified, returns the current source radius accessor, which defaults to:

function radius(d) {
  return d.radius;
}

# ribbon.sourceRadius([radius]) · Source

If radius is specified, sets the source radius accessor to the specified function and returns this ribbon generator. If radius is not specified, returns the current source radius accessor, which defaults to:

function radius(d) {
  return d.radius;
}

# ribbon.targetRadius([radius]) · Source

If radius is specified, sets the target radius accessor to the specified function and returns this ribbon generator. If radius is not specified, returns the current target radius accessor, which defaults to:

function radius(d) {
  return d.radius;
}

By convention, the target radius in asymmetric chord diagrams is typically inset from the source radius, resulting in a gap between the end of the directed link and its associated group arc.

# ribbon.startAngle([angle]) · Source

If angle is specified, sets the start angle accessor to the specified function and returns this ribbon generator. If angle is not specified, returns the current start angle accessor, which defaults to:

function startAngle(d) {
  return d.startAngle;
}

The angle is specified in radians, with 0 at -y (12 o’clock) and positive angles proceeding clockwise.

# ribbon.endAngle([angle]) · Source

If angle is specified, sets the end angle accessor to the specified function and returns this ribbon generator. If angle is not specified, returns the current end angle accessor, which defaults to:

function endAngle(d) {
  return d.endAngle;
}

The angle is specified in radians, with 0 at -y (12 o’clock) and positive angles proceeding clockwise.

# ribbon.padAngle([angle]) · Source

If angle is specified, sets the pad angle accessor to the specified function and returns this ribbon generator. If angle is not specified, returns the current pad angle accessor, which defaults to:

function padAngle() {
  return 0;
}

The pad angle specifies the angular gap between adjacent ribbons.

# ribbon.context([context]) · Source

If context is specified, sets the context and returns this ribbon generator. If context is not specified, returns the current context, which defaults to null. If the context is not null, then the generated ribbon is rendered to this context as a sequence of path method calls. Otherwise, a path data string representing the generated ribbon is returned. See also d3-path.

# d3.ribbonArrow() · Source

Creates a new arrow ribbon generator with the default settings.

# ribbonArrow.headRadius([radius]) · Source

If radius is specified, sets the arrowhead radius accessor to the specified function and returns this ribbon generator. If radius is not specified, returns the current arrowhead radius accessor, which defaults to:

function headRadius() {
  return 10;
}

d3-chord's People

Contributors

dependabot[bot] avatar fil avatar mbostock avatar stof avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

d3-chord's Issues

creating a matrix

The first is a reference file (chr03) which contains one long sequence (35020413 characters long) and the other file contained multiple sequences with different lengths and different ids (tig00007144, tig00026480,...). I used an alignment software called BLAST to align these two sequences. The original alignment results are stored in tab separated file:

tig00007144	chr03	23113	30824	33203431	33211142
tig00026480	chr03	1	48387	35010628	34962190
tig00003221	chr03	16916	29961	2127862	2140878
tig00010111	chr03	218	6989	23106738	23113500
tig00000318	chr03	1	18244	28621116	28639312
tig00009327	chr03	32147	40878	34160279	34151526
tig00025208	chr03	65878	79311	17006900	17020370
tig00019172	chr03	43720	50583	23113500	23106638
tig00004923	chr03	44154	50849	21159875	21153164

This is the column explanation:

  • query_name = column 0
  • subject_name = column 1
  • query_start = column 2
  • query_end = column 3
  • subject_start = column 4]
  • subject_end = column 5

I would like to see which parts (tig00007144, tig00026480, ...) mapping where to chr03.

Any idea how to create such matrix?

Thank you in advance.

Michal

Twisted ribbons between nearby nodes

This is a fantastic layout module and you can do some really wonderful things with!

There is one issue however that is rather difficult to get around from the consumer's side. When drawing ribbons between nearby nodes, they often get "twisted" as follows:

Screen Shot 2019-11-21 at 1 17 27 PM

There's two factors that make this artifact more apparent:

  • The angular proximity between the two nodes
  • The difference in angular widths (endAngle-startAngle) of the source and the target

Afaict, this cannot be counteracted by manipulating any of the ribbon accessor methods.

I believe this is because when computing the two arcs that connect the sides of the ribbon between the source and target, they're both centered at 0,0:

context.arc(0, 0, sr, sa0, sa1);

and
context.arc(0, 0, tr, ta0, ta1);

So, in certain cases the two arcs actually cross each other because their closest point to the center is happening at different angles. This results in the visual "twist".

Perhaps a resolution would be to shift the arc center of the shorter arc closer to the edge of the diagram, just enough so that the two arcs never cross.

Question about sub-groups

Hi,

I guess that the following feature (object hierarchy on the circumference) is not directly supported, but just to make sure, can anyone please explain what are "subgroups" as per the readme of this module? I'm not entirely sure about the groups and subgroups terminology in the docs for chord diagrams.

Thanks in advance!

problems with chord.js in a non-observable environment

The function range line 3-5 in chord.js does not work in a non-observable environment. It gives an array of "undefined" values.

Solution:

function range(i,j) { return [...Array(j-i).keys()].flatMap(j=>j+i) }

In line 100 of chord.js empty chords should be removed by chords = Object.values(chords);
But this also leaves e.g. "functions" in chords and breaks the compareValue function in lines 7-14

Solution:

chords = chords.filter(Object);

Network layout.

Should there be separate layouts for bidirectional flow vs. unidirectional flow? See comment on d3/d3-shape#7.

Should the network take a matrix as input? Or perhaps it should take a list of nodes and a list of weighted links, more like the force layout?

Change chord subgroup default order?

The default subgroup order is range(0, n), which is the same for all groups, and means that chords emanating from a group will often cross paths.

The .sortSubgroups() option allows to reorder the chords according to their values (ie matrix[i,j]), but not to the geometry (ie., is group i to the left or right of j?).

This fork of https://github.com/d3/d3-chord/blob/master/src/chord.js creates a new default order: [i-1, i-2…0, i, n, n-1, n-2… i+1]

With this approach we can limit the number of crossing paths without having to actually care about the actual geometry.

Capture d’écran 2020-09-17 à 11 22 22

Capture d’écran 2020-09-17 à 11 22 33

(If this seems useful we'll have to think about a meaninful API.)

Alphanumeric labels?

Hi,

I'm trying to draw a chord-graph using this script that has two letters as the labels. When I upload the file on Circos, it creates the graph I'm looking for, yet when I try it with this script, I get just a blank page.

What do I have to modify to get it to work?

This is the var matrix I'm using:

var matrix = [
['', 'AF', 'AS', 'EU', 'NA', 'OC', 'SA'],
['AF', 1, 0, 0, 0, 0, 0],
['AS', 6, 79, 0, 0, 0, 0],
['EU', 0, 57, 0, 0, 0, 0],
['NA', 0, 4, 160, 4, 0, 0],
['OC', 0, 17, 0, 0, 0, 0],
['SA', 0, 0, 4, 29, 0, 0],
];

Thanks in advance.

Ribbon positioning in canvas

We are building a force-direct diagram with chords diagrams at each node. We experienced a bug, chords are fixed at the origin of the canvas without any possibility of positioning.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.