-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
[WIP] Transforms [rebase of timelyportfolio's work] #936
Changes from all commits
9bb2b10
582d210
d0ef359
9574f4f
77e2b27
aa1f1d3
6015768
6daeac5
3e0f209
d735b64
a820b0c
2dd3646
c30f94e
e9bde33
c6355e8
5765f66
02742e8
b23d2ff
55f9e0c
462b2f0
9cafe1e
87de31f
61f3385
57d0c13
7085729
392844d
1dd93bb
1ea2fd7
59b741d
a5dad2a
79dcbc3
aa70e4c
523f61b
4efe6a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/** | ||
* 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. | ||
*/ | ||
|
||
module.exports = require('../src/transforms/filter'); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -786,6 +786,41 @@ function applyTransforms(fullTrace, fullData, layout) { | |
var container = fullTrace.transforms, | ||
dataOut = [fullTrace]; | ||
|
||
var attributeSets = dataOut.map(function(trace) { | ||
|
||
var arraySplitAttributes = []; | ||
|
||
var stack = []; | ||
|
||
/** | ||
* A closure that gathers attribute paths into its enclosed arraySplitAttributes | ||
* Attribute paths are collected iff their leaf node is a splittable attribute | ||
* @callback callback | ||
* @param {object} attr an attribute | ||
* @param {String} attrName name string | ||
* @param {object[]} attrs all the attributes | ||
* @param {Number} level the recursion level, 0 at the root | ||
* @closureVariable {String[][]} arraySplitAttributes the set of gathered attributes | ||
* Example of filled closure variable (expected to be initialized to []): | ||
* [["marker","size"],["marker","line","width"],["marker","line","color"]] | ||
*/ | ||
function callback(attr, attrName, attrs, level) { | ||
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. Interesting! Thanks for the docs. This might be applicable in a few situations. |
||
|
||
stack = stack.slice(0, level).concat([attrName]); | ||
|
||
var splittableAttr = attr.valType === 'data_array' || attr.arrayOk === true; | ||
if(splittableAttr) { | ||
arraySplitAttributes.push(stack.slice()); | ||
} | ||
} | ||
|
||
Lib.crawl(trace._module.attributes, callback); | ||
|
||
return arraySplitAttributes.map(function(path) { | ||
return path.join('.'); | ||
}); | ||
}); | ||
|
||
for(var i = 0; i < container.length; i++) { | ||
var transform = container[i], | ||
type = transform.type, | ||
|
@@ -796,7 +831,9 @@ function applyTransforms(fullTrace, fullData, layout) { | |
transform: transform, | ||
fullTrace: fullTrace, | ||
fullData: fullData, | ||
layout: layout | ||
attributeSets: attributeSets, | ||
layout: layout, | ||
transformIndex: i | ||
}); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,20 @@ | ||
/** | ||
* 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 Lib = require('@src/lib'); | ||
var Lib = require('../../../../src/lib'); | ||
var Lib = require('../lib'); | ||
|
||
/* eslint no-unused-vars: 0*/ | ||
|
||
|
||
// so that Plotly.register knows what to do with it | ||
exports.moduleType = 'transform'; | ||
|
||
|
@@ -16,17 +25,21 @@ exports.name = 'filter'; | |
exports.attributes = { | ||
operation: { | ||
valType: 'enumerated', | ||
values: ['=', '<', '>'], | ||
values: ['=', '<', '>', 'within', 'notwithin', 'in', 'notin'], | ||
dflt: '=' | ||
}, | ||
value: { | ||
valType: 'number', | ||
valType: 'any', | ||
dflt: 0 | ||
}, | ||
filtersrc: { | ||
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. Can we add 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. you mean 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. Thank you, yes. I was looking at the wrong branch. |
||
valType: 'enumerated', | ||
values: ['x', 'y'], | ||
dflt: 'x' | ||
values: ['x', 'y', 'ids'], | ||
dflt: 'x', | ||
ids: { | ||
valType: 'data_array', | ||
description: 'A list of keys for object constancy of data points during animation' | ||
} | ||
} | ||
}; | ||
|
||
|
@@ -54,6 +67,16 @@ exports.supplyDefaults = function(transformIn, fullData, layout) { | |
coerce('value'); | ||
coerce('filtersrc'); | ||
|
||
// numeric values as character should be converted to numeric | ||
if(Array.isArray(transformOut.value)) { | ||
transformOut.value = transformOut.value.map(function(v) { | ||
if(isNumeric(v)) v = +v; | ||
return v; | ||
}); | ||
} else { | ||
if(isNumeric(transformOut.value)) transformOut.value = +transformOut.value; | ||
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. I would prefer moving the array item type conversion down to the 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. FYI I haven't touched anything in |
||
} | ||
|
||
// or some more complex logic using fullData and layout | ||
|
||
return transformOut; | ||
|
@@ -121,6 +144,16 @@ function transformOne(trace, state) { | |
|
||
function getFilterFunc(opts) { | ||
var value = opts.value; | ||
// if value is not array then coerce to | ||
// an array of [value,value] so the | ||
// filter function will work | ||
// but perhaps should just error out | ||
var valueArr = []; | ||
if(!Array.isArray(value)) { | ||
valueArr = [value, value]; | ||
} else { | ||
valueArr = value; | ||
} | ||
|
||
switch(opts.operation) { | ||
case '=': | ||
|
@@ -129,6 +162,30 @@ function getFilterFunc(opts) { | |
return function(v) { return v < value; }; | ||
case '>': | ||
return function(v) { return v > value; }; | ||
case 'within': | ||
return function(v) { | ||
// if character then ignore with no side effect | ||
function notDateNumber(d) { | ||
return !(isNumeric(d) || Lib.isDateTime(d)); | ||
} | ||
if(valueArr.some(notDateNumber)) { | ||
return true; | ||
} | ||
|
||
// keep the = ? | ||
return v >= Math.min.apply(null, valueArr) && | ||
v <= Math.max.apply(null, valueArr); | ||
}; | ||
case 'notwithin': | ||
return function(v) { | ||
// keep the = ? | ||
return !(v >= Math.min.apply(null, valueArr) && | ||
v <= Math.max.apply(null, valueArr)); | ||
}; | ||
case 'in': | ||
return function(v) { return valueArr.indexOf(v) >= 0; }; | ||
case 'notin': | ||
return function(v) { return valueArr.indexOf(v) === -1; }; | ||
} | ||
} | ||
|
||
|
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.
Thanks for 📚