Skip to content

Filter and groupby transforms in main bundle #978

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 26 commits into from
Oct 6, 2016
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6309837
fix linting in lib/filter.js
etpinard Sep 26, 2016
96bcbfc
lib: add groupby module + register it in main index
etpinard Sep 26, 2016
06c805d
lint: rm useless comments in transform modules
etpinard Sep 26, 2016
f6eb2f4
lint: rm uselss Plotly.register calls in test suites
etpinard Sep 26, 2016
0158f45
test: move user-defined transform test to transform_multi
etpinard Sep 26, 2016
64dc72a
transforms: make findArrayAttributes a lib function
etpinard Sep 28, 2016
1238236
transforms: add 'calcTransform' handler in doCalcdata
etpinard Sep 28, 2016
0e1e9a7
transforms: filter take II
etpinard Sep 28, 2016
f722c5d
transforms: fill in groupby descriptions
etpinard Sep 28, 2016
037fa5c
transforms: perf in groupby
etpinard Sep 28, 2016
01f8595
lint: some line spacing in plots.js
etpinard Sep 28, 2016
8a29a89
test: one big nasty commit untangling / adding transforms tests
etpinard Sep 28, 2016
ad5089e
test: make sure all '#graph' nodes are purged after toimage tests
etpinard Sep 29, 2016
7a98f15
test: fixup plotschema case for new filter attributes
etpinard Sep 29, 2016
c8a13b8
test: add case where axis type is set by user
etpinard Sep 29, 2016
f4b9dcc
transforms: replace 'active' attribute by 'enabled'
etpinard Sep 30, 2016
104123e
transforms: replace 'strictinterval' with MORE operation values
etpinard Sep 30, 2016
ba9b933
transforms: improve attribute descriptions
etpinard Sep 30, 2016
7fc7dfa
fix a few typos
etpinard Sep 30, 2016
7cfa4ff
transforms: fix logic for outside intervals
etpinard Sep 30, 2016
3e74c80
api: relax transform module requirements
etpinard Oct 3, 2016
2a7738e
api: improve register transform logging and tests
etpinard Oct 3, 2016
0aa4958
test: update transform case descriptions
etpinard Oct 3, 2016
ad77818
transforms: allow 'filtersrc' to be an arbitrary attr string
etpinard Oct 3, 2016
4cd9edf
transforms: add support for date 3D z-axes
etpinard Oct 3, 2016
f5c64d2
doc: add comment about transform in main index file
etpinard Oct 5, 2016
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
2 changes: 2 additions & 0 deletions lib/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
* LICENSE file in the root directory of this source tree.
*/

'use strict';

module.exports = require('../src/transforms/filter');
11 changes: 11 additions & 0 deletions lib/groupby.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* 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';

module.exports = require('../src/transforms/groupby');
6 changes: 4 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

var Plotly = require('./core');

// traces
Plotly.register([
require('./bar'),
require('./box'),
Expand All @@ -30,9 +31,10 @@ Plotly.register([
require('./scattermapbox')
]);

// add transforms
// transforms
Plotly.register([
require('./filter')
require('./filter'),
require('./groupby')
]);

module.exports = Plotly;
50 changes: 50 additions & 0 deletions src/lib/coerce.js
Original file line number Diff line number Diff line change
Expand Up @@ -409,3 +409,53 @@ exports.crawl = function(attrs, callback, specifiedLevel) {
if(isPlainObject(attr)) exports.crawl(attr, callback, level + 1);
});
};

/**
* Find all data array attributes in a given trace object - including
* `arrayOk` attributes.
*
* @param {object} trace
* full trace object that contains a reference to `_module.attributes`
*
* @return {array} arrayAttributes
* list of array attributes for the given trace
*/
exports.findArrayAttributes = function(trace) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@monfera FYI I decided to make findArrayAttributes a lib function instead meant to be called on-demand by the transform modules.

That way, this same function can now find the array attributes per trace module and filter them to match the array attribute in the user trace.

var arrayAttributes = [],
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[][]} arrayAttributes 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) {
stack = stack.slice(0, level).concat([attrName]);

var splittableAttr = attr.valType === 'data_array' || attr.arrayOk === true;
if(!splittableAttr) return;

var astr = toAttrString(stack);
var val = nestedProperty(trace, astr).get();
if(!Array.isArray(val)) return;

arrayAttributes.push(astr);
}

function toAttrString(stack) {
return stack.join('.');
}

exports.crawl(trace._module.attributes, callback);

return arrayAttributes;
};
1 change: 1 addition & 0 deletions src/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ lib.coerceFont = coerceModule.coerceFont;
lib.validate = coerceModule.validate;
lib.isValObject = coerceModule.isValObject;
lib.crawl = coerceModule.crawl;
lib.findArrayAttributes = coerceModule.findArrayAttributes;
lib.IS_SUBPLOT_OBJ = coerceModule.IS_SUBPLOT_OBJ;
lib.IS_LINKED_TO_ARRAY = coerceModule.IS_LINKED_TO_ARRAY;
lib.DEPRECATED = coerceModule.DEPRECATED;
Expand Down
70 changes: 28 additions & 42 deletions src/plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ var Plotly = require('../plotly');
var Registry = require('../registry');
var Lib = require('../lib');
var Color = require('../components/color');

var plots = module.exports = {};

var animationAttrs = require('./animation_attributes');
var frameAttrs = require('./frame_attributes');

Expand Down Expand Up @@ -786,52 +788,15 @@ 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) {

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,
_module = transformsRegistry[type];
_module = transformsRegistry[transform.type];

if(_module) {
dataOut = _module.transform(dataOut, {
transform: transform,
fullTrace: fullTrace,
fullData: fullData,
attributeSets: attributeSets,
layout: layout,
transformIndex: i
});
Expand Down Expand Up @@ -1617,7 +1582,7 @@ plots.doCalcdata = function(gd, traces) {
var axList = Plotly.Axes.list(gd),
fullData = gd._fullData,
fullLayout = gd._fullLayout,
i;
i, j;

// XXX: Is this correct? Needs a closer look so that *some* traces can be recomputed without
// *all* needing doCalcdata:
Expand Down Expand Up @@ -1655,7 +1620,6 @@ plots.doCalcdata = function(gd, traces) {
}

var trace = fullData[i],
_module = trace._module,
cd = [];

// If traces were specified and this trace was not included, then transfer it over from
Expand All @@ -1665,8 +1629,30 @@ plots.doCalcdata = function(gd, traces) {
continue;
}

if(_module && trace.visible === true) {
if(_module.calc) cd = _module.calc(gd, trace);
var _module;
if(trace.visible === true) {

// call calcTransform method if any
if(trace.transforms) {

// we need one round of trace module calc before
// the calc transform to 'fill in' the categories list
// used for example in the data-to-coordinate method
_module = trace._module;
if(_module && _module.calc) _module.calc(gd, trace);

for(j = 0; j < trace.transforms.length; j++) {
var transform = trace.transforms[j];

_module = transformsRegistry[transform.type];
if(_module && _module.calcTransform) {
_module.calcTransform(gd, trace, transform);
}
}
}

_module = trace._module;
if(_module && _module.calc) cd = _module.calc(gd, trace);
}

// make sure there is a first point
Expand Down
Loading