8000 fixup transform api · rowhit/plotly.js@7d54249 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7d54249

Browse files
committed
fixup transform api
1 parent 034290e commit 7d54249

File tree

3 files changed

+109
-61
lines changed

3 files changed

+109
-61
lines changed

src/plots/plots.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ plots.supplyDataDefaults = function(dataIn, dataOut, layout, modules) {
620620
var traceIn = fullTrace._input;
621621

622622
if(fullTrace.transforms && fullTrace.transforms.length) {
623-
var expandedTraces = applyTransforms(fullTrace, layout);
623+
var expandedTraces = applyTransforms(fullTrace, dataOut, layout);
624624

625625
for(var j = 0; j < expandedTraces.length; j++) {
626626
var expandedTrace = expandedTraces[j];
@@ -733,18 +733,21 @@ function supplyTransformDefaults(traceIn, traceOut, layout) {
733733
}
734734
}
735735

736-
function applyTransforms(fullTrace, layout) {
736+
function applyTransforms(fullTrace, fullData, layout) {
737737
var container = fullTrace.transforms,
738-
dataOut = [];
738+
dataOut = [fullTrace];
739739

740740
for(var i = 0; i < container.length; i++) {
741741
var transform = container[i],
742742
type = transform.type,
743743
_module = transformsRegistry[type];
744744

745-
dataOut = dataOut.concat(_module.transform(transform, fullTrace, layout));
746-
747-
// TODO need to compose transforms !!!
745+
dataOut = _module.transform(dataOut, {
746+
transform: transform,
747+
fullTrace: fullTrace,
748+
fullData: fullData,
749+
layout: layout
750+
});
748751
}
749752

750753
return dataOut;

test/jasmine/assets/transforms/filter.js

Lines changed: 67 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -62,56 +62,62 @@ exports.supplyDefaults = function(transformIn, fullData, layout) {
6262
/**
6363
* Apply transform !!!
6464
*
65-
* @param {object} opts
66-
* full transform options
67-
* @param {object} fullTrace
68-
* full trace object where the transform is nested
69-
* @param {object} layout
70-
* the plot's (not-so-full) layout
65+
* @param {array} data
66+
* array of transformed traces (is [fullTrace] upon first transform)
67+
*
68+
* @param {object} state
69+
* state object which includes:
70+
* - transform {object} full transform attributes
71+
* - fullTrace {object} full trace object which is being transformed
72+
* - fullData {array} full pre-transform(s) data array
73+
* - layout {object} the plot's (not-so-full) layout
7174
*
72 57AE -
* @return {object} dataOut
75+
* @return {object} newData
7376
* array of transformed traces
7477
*/
75-
exports.transform = function(opts, fullTrace, layout) {
78+
exports.transform = function(data, state) {
7679

7780
// one-to-one case
78-
//
79-
// TODO is this the best pattern ???
80-
// maybe we could abstract this out
81-
var traceOut = Lib.extendDeep({}, fullTrace);
82-
delete traceOut.transforms;
8381

84-
traceOut.x = [];
85-
traceOut.y = [];
82+
var newData = data.map(function(trace) {
83+
return transformOne(trace, state);
84+
});
85+
86+
return newData;
87+
};
8688

89+
function transformOne(trace, state) {
90+
var newTrace = Lib.extendDeep({}, trace);
91+
92+
var opts = state.transform;
93+
var src = opts.filtersrc;
8794
var filterFunc = getFilterFunc(opts);
95+
var len = trace[src].length;
96+
var arrayAttrs = findArrayAttributes(trace);
97+
98+
arrayAttrs.forEach(function(attr) {
99+
Lib.nestedProperty(newTrace, attr).set([]);
100+
});
88101

89-
var src, opp, len;
90-
switch(opts.filtersrc) {
91-
case 'x':
92-
src = 'x';
93-
opp = 'y';
94-
len = fullTrace.x.length;
95-
break;
96-
97-
case 'y':
98-
src = 'y';
99-
opp = 'x';
100-
len = fullTrace.y.length;
101-
break;
102+
function fill(attr, i) {
103+
var arr = Lib.nestedProperty(trace, attr).get();
104+
var newArr = Lib.nestedProperty(newTrace, attr).get();
105+
106+
newArr.push(arr[i]);
102107
}
103108

104109
for(var i = 0; i < len; i++) {
105-
var v = fullTrace[src][i];
110+
var v = trace[src][i];
106111

107112
if(!filterFunc(v)) continue;
108113

109-
traceOut[src].push(v);
110-
traceOut[opp].push(fullTrace[opp][i]);
114+
for(var j = 0; j < arrayAttrs.length; j++) {
115+
fill(arrayAttrs[j], i);
116+
}
111117
}
112118

113-
return [traceOut];
114-
};
119+
return newTrace;
120+
}
115121

116122
function getFilterFunc(opts) {
117123
var value = opts.value;
@@ -125,3 +131,31 @@ function getFilterFunc(opts) {
125131
return function(v) { return v > value; };
126132
}
127133
}
134+
135+
function findArrayAttributes(obj, root) {
136+
root = root || '';
137+
138+
var list = [];
139+
140+
Object.keys(obj).forEach(function(k) {
141+
var val = obj[k];
142+
143+
if(k.charAt(0) === '_') return;
144+
145+
if(k === 'transforms') {
146+
val.forEach(function(item, i) {
147+
list = list.concat(
148+
findArrayAttributes(item, root + k + '[' + i + ']' + '.')
149+
);
150+
});
151+
}
152+
else if(Lib.isPlainObject(val)) {
153+
list = list.concat(findArrayAttributes(val, root + k + '.'));
154+
}
155+
else if(Array.isArray(val)) {
156+
list.push(root + k);
157+
}
158+
});
159+
160+
return list;
161+
}

test/jasmine/assets/transforms/groupby.js

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,52 +63,63 @@ exports.supplyDefaults = function(transformIn, fullData, layout) {
6363
/**
6464
* Apply transform !!!
6565
*
66-
* @param {object} opts
67-
* full transform options
68-
* @param {object} fullTrace
69-
* full trace object where the transform is nested
70-
* @param {object} layout
71-
* the plot's (not-so-full) layout
66+
* @param {array} data
67+
* array of transformed traces (is [fullTrace] upon first transform)
68+
*
69+
* @param {object} state
70+
* state object which includes:
71+
* - transform {object} full transform attributes
72+
* - fullTrace {object} full trace object which is being transformed
73+
* - fullData {array} full pre-transform(s) data array
74+
* - layout {object} the plot's (not-so-full) layout
7275
*
73-
* @return {object} dataOut
76+
* @return {object} newData
7477
* array of transformed traces
7578
*/
76-
exports.transform = function(opts, fullTrace, layout) {
79+
exports.transform = function(data, state) {
7780

7881
// one-to-many case
7982

83+
var newData = [];
84+
85+
data.forEach(function(trace) {
86+
newData = newData.concat(transformOne(trace, state));
87+
});
88+
89+
return newData;
90+
};
91+
92+
function transformOne(trace, state) {
93+
var opts = state.transform;
8094
var groups = opts.groups;
8195

8296
var groupNames = groups.filter(function(g, i, self) {
8397
return self.indexOf(g) === i;
8498
});
8599

86-
var dataOut = new Array(groupNames.length);
87-
var len = Math.min(fullTrace.x.length, fullTrace.y.length, groups.length);
100+
var newData = new Array(groupNames.length);
101+
var len = Math.min(trace.x.length, trace.y.length, groups.length);
88102

89103
for(var i = 0; i < groupNames.length; i++) {
90104
var groupName = groupNames[i];
91105

92106
// TODO is this the best pattern ???
93107
// maybe we could abstract this out
94-
var traceOut = dataOut[i] = Lib.extendDeep({}, fullTrace);
108+
var newTrace = newData[i] = Lib.extendDeep({}, trace);
95109

96-
traceOut.x = [];
97-
traceOut.y = [];
98-
delete traceOut.transforms;
110+
newTrace.x = [];
111+
newTrace.y = [];
99112

100113
for(var j = 0; j < len; j++) {
101114
if(groups[j] !== groupName) continue;
102115

103-
traceOut.x.push(fullTrace.x[j]);
104-
traceOut.y.push(fullTrace.y[j]);
116+
newTrace.x.push(trace.x[j]);
117+
newTrace.y.push(trace.y[j]);
105118
}
106119

107-
traceOut.name = groupName;
108-
traceOut.marker.color = opts.groupColors[groupName];
120+
newTrace.name = groupName;
121+
newTrace.marker.color = opts.groupColors[groupName];
109122
}
110123

111-
// console.log(dataOut);
112-
113-
return dataOut;
114-
};
124+
return newData;
125+
}

0 commit comments

Comments
 (0)
0