Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions draftlogs/7873_add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Add `sort` option to Sankey nodes [[#7873](https://github.com/plotly/plotly.js/pull/7873)]
10 changes: 10 additions & 0 deletions src/traces/sankey/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,16 @@ var attrs = (module.exports = overrideAll(
dflt: 'justify',
description: 'Sets the alignment method used to position the nodes along the horizontal axis.'
},
sort: {
valType: 'enumerated',
values: ['auto', 'input'],
dflt: 'auto',
description: [
'If the value is `auto` (the default), the vertical order of nodes will be determined automatically',
'by the layout.',
'If the value is `input`, the vertical order is kept the same as the order in the input node array'
Comment on lines +178 to +180

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'If the value is `auto` (the default), the vertical order of nodes will be determined automatically',
'by the layout.',
'If the value is `input`, the vertical order is kept the same as the order in the input node array'
'For `auto` (the default), the vertical order of nodes will be determined automatically by the layout.',
'For `input`, the vertical order of nodes is kept the same as the order in the input array.'

].join(' ')
},
description: 'The nodes of the Sankey plot.'
},

Expand Down
1 change: 1 addition & 0 deletions src/traces/sankey/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
handleHoverLabelDefaults(nodeIn, nodeOut, coerceNode, hoverlabelDefault);
coerceNode('hovertemplate');
coerceNode('align');
coerceNode('sort');

var colors = layout.colorway;

Expand Down
10 changes: 10 additions & 0 deletions src/traces/sankey/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ function sankeyModel(layout, d, traceIndex) {
right: d3Sankey.sankeyRight,
center: d3Sankey.sankeyCenter
}[trace.node.align];
var input_sort = trace.node.sort === 'input';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var input_sort = trace.node.sort === 'input';
const inputNodeSort = trace.node.sort === 'input';


var width = layout.width * (domain.x[1] - domain.x[0]);
var height = layout.height * (domain.y[1] - domain.y[0]);
Expand All @@ -48,6 +49,10 @@ function sankeyModel(layout, d, traceIndex) {
var links = calcData._links;
var circular = calcData.circular;

if(circular && input_sort) {
Lib.error('Circular Sankey diagrams do not support the "input" node.sort mode; falling back to the default sort.');
}

Comment on lines +52 to +55

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if(circular && input_sort) {
Lib.error('Circular Sankey diagrams do not support the "input" node.sort mode; falling back to the default sort.');
}

// Select Sankey generator
var sankey;
if(circular) {
Expand All @@ -70,6 +75,11 @@ function sankeyModel(layout, d, traceIndex) {
.nodes(nodes)
.links(links);

// d3-sankey-circular does not support the nodeSort method
if(!circular) {
sankey.nodeSort(input_sort ? null : undefined);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
if (inputNodeSort) {
if (circular) {
Lib.warn('Circular Sankey diagrams do not support the "input" node.sort mode; falling back to the default sort.');
} else {
// Passing null keeps nodes in their input order
sankey.nodeSort(null);
}
}


var graph = sankey();

if(sankey.nodePadding() < nodePad) {
Expand Down
5 changes: 5 additions & 0 deletions src/types/generated/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6837,6 +6837,11 @@ export interface SankeyData {
* Minimum: 0
*/
pad?: number;
/**
* If the value is `auto` (the default), the vertical order of nodes will be determined automatically by the layout. If the value is `input`, the vertical order is kept the same as the order in the input node array
* @default 'auto'
*/
sort?: 'auto' | 'input';
/**
* Sets the thickness (in px) of the `nodes`.
* @default 20
Expand Down
Binary file added test/image/baselines/sankey_auto_sort.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/image/baselines/sankey_input_sort.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions test/image/mocks/sankey_auto_sort.json

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this mock can be deleted since all of the other sankey mocks use the auto sort.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"data": [
{
"type": "sankey",
"node": {
"label": ["0", "1", "2", "3", "4", "5"],
"align": "center",
"sort": "auto"
},
"link": {
"source": [0, 0, 0, 0, 1, 4],
"target": [1, 2, 3, 4, 5, 5],
"value": [1, 2, 1, 1, 1, 1]
}
}
],
"layout": {
"title": { "text": "Sankey with automatic vertical node ordering" },
"width": 800,
"height": 800
}
}
22 changes: 22 additions & 0 deletions test/image/mocks/sankey_input_sort.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"data": [
{
"type": "sankey",
"node": {
"label": ["0", "1", "2", "3", "4", "5"],
"align": "center",
"sort": "input"
},
"link": {
"source": [0, 0, 0, 0, 1, 4],
"target": [1, 2, 3, 4, 5, 5],
"value": [1, 2, 1, 1, 1, 1]
}
}
],
"layout": {
"title": { "text": "Sankey with fixed vertical node ordering" },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"title": { "text": "Sankey with fixed vertical node ordering" },
"title": { "text": "Sankey with vertical node ordering matching the input array" },

"width": 800,
"height": 800
}
}
21 changes: 21 additions & 0 deletions test/jasmine/tests/sankey_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,27 @@ describe('sankey tests', function () {
.then(done, done.fail);
});

it('falls back to the default sort for circular Sankey with node.sort set', function (done) {
var errors = [];
spyOn(Lib, 'error').and.callFake(function (msg) {
errors.push(msg);
});
Comment on lines +505 to +508

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var errors = [];
spyOn(Lib, 'error').and.callFake(function (msg) {
errors.push(msg);
});
var warnings = [];
spyOn(Lib, 'warn').and.callFake(function (msg) {
warnings.push(msg);
});


var mockCircularCopy = Lib.extendDeep({}, mockCircular);
mockCircularCopy.data[0].node.sort = 'input';

Plotly.newPlot(gd, mockCircularCopy)
.then(function () {
// The plot renders successfully
expect(gd.calcdata[0][0].circular).toBe(true);
expect(d3SelectAll('.sankey .node-rect').size()).toBeGreaterThan(0);

// An error is logged about the fallback
expect(errors.length).toBe(1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
expect(errors.length).toBe(1);
expect(warnings.length).toBe(1);

})
.then(done, done.fail);
});

it('can create groups, restyle groups and properly update DOM', function (done) {
var mockCircularCopy = Lib.extendDeep({}, mockCircular);
var firstGroup = [
Expand Down
10 changes: 10 additions & 0 deletions test/plot-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -50746,6 +50746,16 @@
"valType": "number"
},
"role": "object",
"sort": {
"description": "If the value is `auto` (the default), the vertical order of nodes will be determined automatically by the layout. If the value is `input`, the vertical order is kept the same as the order in the input node array",
"dflt": "auto",
"editType": "calc",
"valType": "enumerated",
"values": [
"auto",
"input"
]
},
"thickness": {
"arrayOk": false,
"description": "Sets the thickness (in px) of the `nodes`.",
Expand Down
Loading