-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Box trace directory split into multiple files #158
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
Changes from 5 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
db3540f
Box trace directory split into multiple files
mdtusz 3d9509d
Fixed missing variable
mdtusz eba8b83
Box trace directory split into multiple files
mdtusz af7f8e3
Fixed missing variable
mdtusz 953c42b
Merge branch 'box-trace-cleaning' of github.com:plotly/plotly.js into…
mdtusz d9a6948
Added new 2016 header
mdtusz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
'use strict'; | ||
|
||
var isNumeric = require('fast-isnumeric'); | ||
|
||
var Plotly = require('../../plotly'); | ||
var Lib = require('../../lib'); | ||
|
||
module.exports = function calc(gd, trace) { | ||
// outlier definition based on http://www.physics.csbsju.edu/stats/box2.html | ||
var xa = Plotly.Axes.getFromId(gd, trace.xaxis||'x'), | ||
ya = Plotly.Axes.getFromId(gd, trace.yaxis||'y'), | ||
orientation = trace.orientation, | ||
cd = [], | ||
valAxis, valLetter, val, valBinned, | ||
posAxis, posLetter, pos, posDistinct, dPos; | ||
|
||
// Set value (val) and position (pos) keys via orientation | ||
if (orientation==='h') { | ||
valAxis = xa; | ||
valLetter = 'x'; | ||
posAxis = ya; | ||
posLetter = 'y'; | ||
} else { | ||
valAxis = ya; | ||
valLetter = 'y'; | ||
posAxis = xa; | ||
posLetter = 'x'; | ||
} | ||
|
||
val = valAxis.makeCalcdata(trace, valLetter); // get val | ||
|
||
// size autorange based on all source points | ||
// position happens afterward when we know all the pos | ||
Plotly.Axes.expand(valAxis, val, {padded: true}); | ||
|
||
// In vertical (horizontal) box plots: | ||
// if no x (y) data, use x0 (y0), or name | ||
// so if you want one box | ||
// per trace, set x0 (y0) to the x (y) value or category for this trace | ||
// (or set x (y) to a constant array matching y (x)) | ||
function getPos (gd, trace, posLetter, posAxis, val) { | ||
var pos0; | ||
if (posLetter in trace) pos = posAxis.makeCalcdata(trace, posLetter); | ||
else { | ||
if (posLetter+'0' in trace) pos0 = trace[posLetter+'0']; | ||
else if ('name' in trace && ( | ||
posAxis.type==='category' || | ||
(isNumeric(trace.name) && | ||
['linear','log'].indexOf(posAxis.type)!==-1) || | ||
(Lib.isDateTime(trace.name) && | ||
posAxis.type==='date') | ||
)) { | ||
pos0 = trace.name; | ||
} | ||
else pos0 = gd.numboxes; | ||
pos0 = posAxis.d2c(pos0); | ||
pos = val.map(function(){ return pos0; }); | ||
} | ||
return pos; | ||
} | ||
|
||
pos = getPos(gd, trace, posLetter, posAxis, val); | ||
|
||
// get distinct positions and min difference | ||
var dv = Lib.distinctVals(pos); | ||
posDistinct = dv.vals; | ||
dPos = dv.minDiff/2; | ||
|
||
function binVal (cd, val, pos, posDistinct, dPos) { | ||
var posDistinctLength = posDistinct.length, | ||
valLength = val.length, | ||
valBinned = [], | ||
bins = [], | ||
i, p, n, v; | ||
|
||
// store distinct pos in cd, find bins, init. valBinned | ||
for (i = 0; i < posDistinctLength; ++i) { | ||
p = posDistinct[i]; | ||
cd[i] = {pos: p}; | ||
bins[i] = p - dPos; | ||
valBinned[i] = []; | ||
} | ||
bins.push(posDistinct[posDistinctLength-1] + dPos); | ||
|
||
// bin the values | ||
for (i = 0; i < valLength; ++i) { | ||
v = val[i]; | ||
if(!isNumeric(v)) continue; | ||
n = Lib.findBin(pos[i], bins); | ||
if(n>=0 && n<valLength) valBinned[n].push(v); | ||
} | ||
|
||
return valBinned; | ||
} | ||
|
||
valBinned = binVal(cd, val, pos, posDistinct, dPos); | ||
|
||
// sort the bins and calculate the stats | ||
function calculateStats (cd, valBinned) { | ||
var v, l, cdi, i; | ||
|
||
for (i = 0; i < valBinned.length; ++i) { | ||
v = valBinned[i].sort(Lib.sorterAsc); | ||
l = v.length; | ||
cdi = cd[i]; | ||
|
||
cdi.val = v; // put all values into calcdata | ||
cdi.min = v[0]; | ||
cdi.max = v[l-1]; | ||
cdi.mean = Lib.mean(v,l); | ||
cdi.sd = Lib.stdev(v,l,cdi.mean); | ||
cdi.q1 = Lib.interp(v, 0.25); // first quartile | ||
cdi.med = Lib.interp(v, 0.5); // median | ||
cdi.q3 = Lib.interp(v, 0.75); // third quartile | ||
// lower and upper fences - last point inside | ||
// 1.5 interquartile ranges from quartiles | ||
cdi.lf = Math.min(cdi.q1, v[ | ||
Math.min(Lib.findBin(2.5*cdi.q1-1.5*cdi.q3,v,true)+1, l-1)]); | ||
cdi.uf = Math.max(cdi.q3,v[ | ||
Math.max(Lib.findBin(2.5*cdi.q3-1.5*cdi.q1,v), 0)]); | ||
// lower and upper outliers - 3 IQR out (don't clip to max/min, | ||
// this is only for discriminating suspected & far outliers) | ||
cdi.lo = 4*cdi.q1-3*cdi.q3; | ||
cdi.uo = 4*cdi.q3-3*cdi.q1; | ||
} | ||
} | ||
|
||
calculateStats(cd, valBinned); | ||
|
||
// remove empty bins | ||
cd = cd.filter(function(cdi){ return cdi.val && cdi.val.length; }); | ||
if(!cd.length) return [{t: {emptybox: true}}]; | ||
|
||
// add numboxes and dPos to cd | ||
cd[0].t = {boxnum: gd.numboxes, dPos: dPos}; | ||
gd.numboxes++; | ||
return cd; | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
'use strict'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto |
||
|
||
var Lib = require('../../lib'); | ||
var Color = require('../../components/color'); | ||
|
||
var attributes = require('./attributes'); | ||
|
||
module.exports = function supplyDefaults(traceIn, traceOut, defaultColor) { | ||
function coerce(attr, dflt) { | ||
return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); | ||
} | ||
|
||
var y = coerce('y'), | ||
x = coerce('x'), | ||
defaultOrientation; | ||
|
||
if (y && y.length) { | ||
defaultOrientation = 'v'; | ||
if (!x) coerce('x0'); | ||
} else if (x && x.length) { | ||
defaultOrientation = 'h'; | ||
coerce('y0'); | ||
} else { | ||
traceOut.visible = false; | ||
return; | ||
} | ||
|
||
coerce('orientation', defaultOrientation); | ||
|
||
coerce('line.color', (traceIn.marker||{}).color || defaultColor); | ||
coerce('line.width', 2); | ||
coerce('fillcolor', Color.addOpacity(traceOut.line.color, 0.5)); | ||
|
||
coerce('whiskerwidth'); | ||
coerce('boxmean'); | ||
|
||
var outlierColorDflt = Lib.coerce2(traceIn, traceOut, attributes, 'marker.outliercolor'), | ||
lineoutliercolor = coerce('marker.line.outliercolor'), | ||
boxpoints = outlierColorDflt || | ||
lineoutliercolor ? coerce('boxpoints', 'suspectedoutliers') : | ||
coerce('boxpoints'); | ||
|
||
if(boxpoints) { | ||
coerce('jitter', boxpoints==='all' ? 0.3 : 0); | ||
coerce('pointpos', boxpoints==='all' ? -1.5 : 0); | ||
|
||
coerce('marker.symbol'); | ||
coerce('marker.opacity'); | ||
coerce('marker.size'); | ||
coerce('marker.color', traceOut.line.color); | ||
coerce('marker.line.color'); | ||
coerce('marker.line.width'); | ||
|
||
if(boxpoints==='suspectedoutliers') { | ||
coerce('marker.line.outliercolor', traceOut.marker.color); | ||
coerce('marker.line.outlierwidth'); | ||
} | ||
} | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
'use strict'; | ||
|
||
var Plotly = require('../../plotly'); | ||
var Color = require('../../components/color'); | ||
|
||
module.exports = function hoverPoints(pointData, xval, yval, hovermode) { | ||
// closest mode: handicap box plots a little relative to others | ||
var cd = pointData.cd, | ||
trace = cd[0].trace, | ||
t = cd[0].t, | ||
xa = pointData.xa, | ||
ya = pointData.ya, | ||
closeData = [], | ||
dx, dy, distfn, boxDelta, | ||
posLetter, posAxis, posText, | ||
val, valLetter, valAxis; | ||
|
||
// adjust inbox w.r.t. to calculate box size | ||
boxDelta = (hovermode==='closest') ? 2.5*t.bdPos : t.bdPos; | ||
|
||
if (trace.orientation==='h') { | ||
dx = function(di){ | ||
return Plotly.Fx.inbox(di.min - xval, di.max - xval); | ||
}; | ||
dy = function(di){ | ||
var pos = di.pos + t.bPos - yval; | ||
return Plotly.Fx.inbox(pos - boxDelta, pos + boxDelta); | ||
}; | ||
posLetter = 'y'; | ||
posAxis = ya; | ||
valLetter = 'x'; | ||
valAxis = xa; | ||
} else { | ||
dx = function(di){ | ||
var pos = di.pos + t.bPos - xval; | ||
return Plotly.Fx.inbox(pos - boxDelta, pos + boxDelta); | ||
}; | ||
dy = function(di){ | ||
return Plotly.Fx.inbox(di.min - yval, di.max - yval); | ||
}; | ||
posLetter = 'x'; | ||
posAxis = xa; | ||
valLetter = 'y'; | ||
valAxis = ya; | ||
} | ||
|
||
distfn = Plotly.Fx.getDistanceFunction(hovermode, dx, dy); | ||
Plotly.Fx.getClosest(cd, distfn, pointData); | ||
|
||
// skip the rest (for this trace) if we didn't find a close point | ||
if(pointData.index===false) return; | ||
|
||
// create the item(s) in closedata for this point | ||
|
||
// the closest data point | ||
var di = cd[pointData.index], | ||
lc = trace.line.color, | ||
mc = (trace.marker||{}).color; | ||
if(Color.opacity(lc) && trace.line.width) pointData.color = lc; | ||
else if(Color.opacity(mc) && trace.boxpoints) pointData.color = mc; | ||
else pointData.color = trace.fillcolor; | ||
|
||
pointData[posLetter+'0'] = posAxis.c2p(di.pos + t.bPos - t.bdPos, true); | ||
pointData[posLetter+'1'] = posAxis.c2p(di.pos + t.bPos + t.bdPos, true); | ||
|
||
posText = Plotly.Axes.tickText(posAxis, posAxis.c2l(di.pos), 'hover').text; | ||
pointData[posLetter+'LabelVal'] = di.pos; | ||
|
||
// box plots: each "point" gets many labels | ||
var usedVals = {}, | ||
attrs = ['med','min','q1','q3','max'], | ||
attr, | ||
pointData2; | ||
if(trace.boxmean) attrs.push('mean'); | ||
if(trace.boxpoints) [].push.apply(attrs,['lf', 'uf']); | ||
|
||
for (var i=0; i<attrs.length; i++) { | ||
attr = attrs[i]; | ||
|
||
if(!(attr in di) || (di[attr] in usedVals)) continue; | ||
usedVals[di[attr]] = true; | ||
|
||
// copy out to a new object for each value to label | ||
val = valAxis.c2p(di[attr], true); | ||
pointData2 = Plotly.Lib.extendFlat({}, pointData); | ||
pointData2[valLetter+'0'] = pointData2[valLetter+'1'] = val; | ||
pointData2[valLetter+'LabelVal'] = di[attr]; | ||
pointData2.attr = attr; | ||
|
||
if(attr==='mean' && ('sd' in di) && trace.boxmean==='sd') { | ||
pointData2[valLetter+'err'] = di.sd; | ||
} | ||
pointData.name = ''; // only keep name on the first item (median) | ||
closeData.push(pointData2); | ||
} | ||
return closeData; | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
paste the license header from another file here.
Better yet, maybe you add a no-header-found clause in https://github.com/plotly/plotly.js/blob/master/tasks/header.js#L50 to do it automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh I thought there was a check to automatically insert it already. I'll do it manually right now, but that will be a good thing to add in.