Skip to content
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

Pie trace cleaning #159

Merged
merged 2 commits into from
Jan 5, 2016
Merged
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 src/traces/pie/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* LICENSE file in the root directory of this source tree.
*/

'use strict';
Copy link
Contributor

Choose a reason for hiding this comment

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

there's no functions in this file, so no need for 'use strict';

That said, I don't mind making 'use strict' for all files even the one without functions.

Copy link
Contributor

Choose a reason for hiding this comment

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

@bpostlethwaite what's your take on ⏫ ?

Copy link
Member

Choose a reason for hiding this comment

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

I am inclined to put it everywhere so we don't have to think about it

Copy link
Contributor

Choose a reason for hiding this comment

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

@bpostlethwaite 🍻 thanks


var colorAttrs = require('../../components/color/attributes');
var fontAttrs = require('../../plots/font_attributes');
Expand Down
145 changes: 145 additions & 0 deletions src/traces/pie/calc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var isNumeric = require('fast-isnumeric');
var tinycolor = require('tinycolor2');

var Color = require('../../components/color');
var helpers = require('./helpers');

module.exports = function calc(gd, trace) {
var vals = trace.values,
labels = trace.labels,
cd = [],
fullLayout = gd._fullLayout,
colorMap = fullLayout._piecolormap,
allThisTraceLabels = {},
needDefaults = false,
vTotal = 0,
hiddenLabels = fullLayout.hiddenlabels || [],
i,
v,
label,
color,
hidden,
pt;

if(trace.dlabel) {
labels = new Array(vals.length);
for(i = 0; i < vals.length; i++) {
labels[i] = String(trace.label0 + i * trace.dlabel);
}
}

for(i = 0; i < vals.length; i++) {
v = vals[i];
if(!isNumeric(v)) continue;
v = +v;
if(v < 0) continue;

label = labels[i];
if(label === undefined || label === '') label = i;
label = String(label);
// only take the first occurrence of any given label.
// TODO: perhaps (optionally?) sum values for a repeated label?
if(allThisTraceLabels[label] === undefined) allThisTraceLabels[label] = true;
else continue;

color = tinycolor(trace.marker.colors[i]);
if(color.isValid()) {
color = Color.addOpacity(color, color.getAlpha());
if(!colorMap[label]) {
colorMap[label] = color;
}
}
// have we seen this label and assigned a color to it in a previous trace?
else if(colorMap[label]) color = colorMap[label];
// color needs a default - mark it false, come back after sorting
else {
color = false;
needDefaults = true;
}

hidden = hiddenLabels.indexOf(label) !== -1;

if(!hidden) vTotal += v;

cd.push({
v: v,
label: label,
color: color,
i: i,
hidden: hidden
});
}

if(trace.sort) cd.sort(function(a, b) { return b.v - a.v; });

/**
* now go back and fill in colors we're still missing
* this is done after sorting, so we pick defaults
* in the order slices will be displayed
*/

if(needDefaults) {
for(i = 0; i < cd.length; i++) {
pt = cd[i];
if(pt.color === false) {
colorMap[pt.label] = pt.color = nextDefaultColor(fullLayout._piedefaultcolorcount);
fullLayout._piedefaultcolorcount++;
}
}
}

// include the sum of all values in the first point
if(cd[0]) cd[0].vTotal = vTotal;

// now insert text
if(trace.textinfo && trace.textinfo !== 'none') {
var hasLabel = trace.textinfo.indexOf('label') !== -1,
hasText = trace.textinfo.indexOf('text') !== -1,
hasValue = trace.textinfo.indexOf('value') !== -1,
hasPercent = trace.textinfo.indexOf('percent') !== -1,
thisText;

for(i = 0; i < cd.length; i++) {
pt = cd[i];
thisText = hasLabel ? [pt.label] : [];
if(hasText && trace.text[pt.i]) thisText.push(trace.text[pt.i]);
if(hasValue) thisText.push(helpers.formatPieValue(pt.v));
if(hasPercent) thisText.push(helpers.formatPiePercent(pt.v / vTotal));
pt.text = thisText.join('<br>');
}
}

return cd;
};

/**
* pick a default color from the main default set, augmented by
* itself lighter then darker before repeating
*/
var pieDefaultColors;

function nextDefaultColor(index) {
if(!pieDefaultColors) {
// generate this default set on demand (but then it gets saved in the module)
var mainDefaults = Color.defaults;
pieDefaultColors = mainDefaults.slice();
for(var i = 0; i < mainDefaults.length; i++) {
pieDefaultColors.push(tinycolor(mainDefaults[i]).lighten(20).toHexString());
}
for(i = 0; i < Color.defaults.length; i++) {
pieDefaultColors.push(tinycolor(mainDefaults[i]).darken(20).toHexString());
}
}

return pieDefaultColors[index % pieDefaultColors.length];
}
82 changes: 82 additions & 0 deletions src/traces/pie/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var Lib = require('../../lib');
var attributes = require('./attributes');

module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
function coerce(attr, dflt) {
return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
}

var coerceFont = Lib.coerceFont;

var vals = coerce('values');
if(!Array.isArray(vals) || !vals.length) {
traceOut.visible = false;
return;
}

var labels = coerce('labels');
if(!Array.isArray(labels)) {
coerce('label0');
coerce('dlabel');
}

var lineWidth = coerce('marker.line.width');
if(lineWidth) coerce('marker.line.color');

var colors = coerce('marker.colors');
if(!Array.isArray(colors)) traceOut.marker.colors = []; // later this will get padded with default colors

coerce('scalegroup');
// TODO: tilt, depth, and hole all need to be coerced to the same values within a scaleegroup
// (ideally actually, depth would get set the same *after* scaling, ie the same absolute depth)
// and if colors aren't specified we should match these up - potentially even if separate pies
// are NOT in the same sharegroup


var textData = coerce('text');
var textInfo = coerce('textinfo', Array.isArray(textData) ? 'text+percent' : 'percent');

coerce('hoverinfo', (layout._dataLength === 1) ? 'label+text+value+percent' : undefined);

if(textInfo && textInfo !== 'none') {
var textPosition = coerce('textposition'),
hasBoth = Array.isArray(textPosition) || textPosition === 'auto',
hasInside = hasBoth || textPosition === 'inside',
hasOutside = hasBoth || textPosition === 'outside';

if(hasInside || hasOutside) {
var dfltFont = coerceFont(coerce, 'textfont', layout.font);
if(hasInside) coerceFont(coerce, 'insidetextfont', dfltFont);
if(hasOutside) coerceFont(coerce, 'outsidetextfont', dfltFont);
}
}

coerce('domain.x');
coerce('domain.y');

// 3D attributes commented out until I finish them in a later PR
// var tilt = coerce('tilt');
// if(tilt) {
// coerce('tiltaxis');
// coerce('depth');
// coerce('shading');
// }

coerce('hole');

coerce('sort');
coerce('direction');
coerce('rotation');

coerce('pull');
};
21 changes: 21 additions & 0 deletions src/traces/pie/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

exports.formatPiePercent = function formatPiePercent(v) {
var vRounded = (v * 100).toPrecision(3);
if(vRounded.indexOf('.') !== -1) return vRounded.replace(/[.]?0+$/,'') + '%';
return vRounded + '%';
};

exports.formatPieValue = function formatPieValue(v) {
var vRounded = v.toPrecision(10);
if(vRounded.indexOf('.') !== -1) return vRounded.replace(/[.]?0+$/,'');
return vRounded;
};
Loading