Skip to content

Sankey: colorscales per component, linked to concentration #3501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Feb 18, 2019
41 changes: 11 additions & 30 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 33 additions & 1 deletion src/traces/sankey/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ var colorAttrs = require('../../components/color/attributes');
var fxAttrs = require('../../components/fx/attributes');
var domainAttrs = require('../../plots/domain').attributes;
var hovertemplateAttrs = require('../../components/fx/hovertemplate_attributes');
var colorAttributes = require('../../components/colorscale/attributes');
var templatedArray = require('../../plot_api/plot_template').templatedArray;

var extendFlat = require('../../lib/extend').extendFlat;
var overrideAll = require('../../plot_api/edit_types').overrideAll;
Expand Down Expand Up @@ -225,7 +227,37 @@ var attrs = module.exports = overrideAll({
description: 'Variables `source` and `target` are node objects.',
keys: ['value', 'label']
}),
description: 'The links of the Sankey plot.'
colorscales: templatedArray('concentrationscales', {
editType: 'calc',
label: {
valType: 'string',
role: 'info',
editType: 'calc',
description: 'The label of the links to color based on their concentration within a flow.',
dflt: ''
},
cmax: {
valType: 'number',
role: 'info',
editType: 'calc',
dflt: 1,
description: [
'Sets the upper bound of the color domain.'
].join('')
},
cmin: {
valType: 'number',
role: 'info',
editType: 'calc',
dflt: 0,
description: [
'Sets the lower bound of the color domain.'
].join('')
},
colorscale: extendFlat(colorAttributes().colorscale, {dflt: [[0, 'white'], [1, 'black']]})
}),
description: 'The links of the Sankey plot.',
role: 'info'
}
}, 'calc', 'nested');
attrs.transforms = undefined;
17 changes: 15 additions & 2 deletions src/traces/sankey/calc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var wrap = require('../../lib/gup').wrap;

var isArrayOrTypedArray = Lib.isArrayOrTypedArray;
var isIndex = Lib.isIndex;

var Colorscale = require('../../components/colorscale');

function convertToD3Sankey(trace) {
var nodeSpec = trace.node;
Expand All @@ -24,8 +24,17 @@ function convertToD3Sankey(trace) {
var hasLinkColorArray = isArrayOrTypedArray(linkSpec.color);
var linkedNodes = {};

var nodeCount = nodeSpec.label.length;
var components = {};
var componentCount = linkSpec.colorscales.length;
var i;
for(i = 0; i < componentCount; i++) {
var cscale = linkSpec.colorscales[i];
var specs = Colorscale.extractScale(cscale, {cLetter: 'c'});
var scale = Colorscale.makeColorScaleFunc(specs);
components[cscale.label] = scale;
}

var nodeCount = nodeSpec.label.length;
for(i = 0; i < linkSpec.value.length; i++) {
var val = linkSpec.value[i];
// remove negative values, but keep zeros with special treatment
Expand All @@ -42,10 +51,14 @@ function convertToD3Sankey(trace) {
var label = '';
if(linkSpec.label && linkSpec.label[i]) label = linkSpec.label[i];

var concentrationscale = null;
if(label && components.hasOwnProperty(label)) concentrationscale = components[label];

links.push({
pointNumber: i,
label: label,
color: hasLinkColorArray ? linkSpec.color[i] : linkSpec.color,
concentrationscale: concentrationscale,
source: source,
target: target,
value: +val
Expand Down
19 changes: 18 additions & 1 deletion src/traces/sankey/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ var tinycolor = require('tinycolor2');
var handleDomainDefaults = require('../../plots/domain').defaults;
var handleHoverLabelDefaults = require('../../components/fx/hoverlabel_defaults');
var Template = require('../../plot_api/plot_template');
var handleArrayContainerDefaults = require('../../plots/array_container_defaults');

module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
function coerce(attr, dflt) {
Expand Down Expand Up @@ -48,7 +49,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
}));

// link attributes
var linkIn = traceIn.link;
var linkIn = traceIn.link || {};
var linkOut = Template.newContainer(traceOut, 'link');

function coerceLink(attr, dflt) {
Expand All @@ -70,6 +71,11 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout

coerceLink('color', Lib.repeat(defaultLinkColor, linkOut.value.length));

handleArrayContainerDefaults(linkIn, linkOut, {
name: 'colorscales',
handleItemDefaults: concentrationscalesDefaults
});

handleDomainDefaults(traceOut, layout, coerce);

coerce('orientation');
Expand All @@ -83,3 +89,14 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
// don't match, between nodes and links
traceOut._length = null;
};

function concentrationscalesDefaults(In, Out) {
function coerce(attr, dflt) {
return Lib.coerce(In, Out, attributes.link.colorscales, attr, dflt);
}

coerce('label');
coerce('cmin');
coerce('cmax');
coerce('colorscale');
}
21 changes: 17 additions & 4 deletions src/traces/sankey/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,21 @@ function linkHoveredStyle(d, sankey, visitNodes, sankeyLink) {

var label = sankeyLink.datum().link.label;

sankeyLink.style('fill-opacity', 0.4);
sankeyLink.style('fill-opacity', function(l) {
if(!l.link.concentrationscale) {
return 0.4;
}
});

if(label) {
ownTrace(sankey, d)
.selectAll('.' + cn.sankeyLink)
.filter(function(l) {return l.link.label === label;})
.style('fill-opacity', 0.4);
.style('fill-opacity', function(l) {
if(!l.link.concentrationscale) {
return 0.4;
}
});
}

if(visitNodes) {
Expand Down Expand Up @@ -143,6 +151,7 @@ module.exports = function plot(gd, calcData) {

var sourceLabel = _(gd, 'source:') + ' ';
var targetLabel = _(gd, 'target:') + ' ';
var concentrationLabel = _(gd, 'concentration:') + ' ';
var incomingLabel = _(gd, 'incoming flow count:') + ' ';
var outgoingLabel = _(gd, 'outgoing flow count:') + ' ';

Expand Down Expand Up @@ -172,7 +181,8 @@ module.exports = function plot(gd, calcData) {
text: [
d.link.label || '',
sourceLabel + d.link.source.label,
targetLabel + d.link.target.label
targetLabel + d.link.target.label,
d.link.concentrationscale ? concentrationLabel + d3.format('%0.2f')(d.link.flow.labelConcentration) : ''
].filter(renderableValuePresent).join('<br>'),
color: castHoverOption(obj, 'bgcolor') || Color.addOpacity(d.tinyColorHue, 1),
borderColor: castHoverOption(obj, 'bordercolor'),
Expand All @@ -190,7 +200,9 @@ module.exports = function plot(gd, calcData) {
gd: gd
});

makeTranslucent(tooltip, 0.65);
if(!d.link.concentrationscale) {
makeTranslucent(tooltip, 0.65);
}
makeTextContrasty(tooltip);
};

Expand Down Expand Up @@ -288,6 +300,7 @@ module.exports = function plot(gd, calcData) {
};

render(
gd,
svg,
calcData,
{
Expand Down
Loading