Skip to content

Commit f9d9c35

Browse files
Working on the annotation tests
It seems that "paper" doesn't work as expected when axref or ayref are set as the same as xref and or yref (who are also set as "paper"). Indeed, the "range" and "domain" reference types do work the new way, where the arrow head can be placed absolutely as long as axref or ayref is exactly the same as the corresponding xref or yref. So "paper" should take up this functionality, or the spec should make it clear that it doesn't work and the test updated accordingly.
1 parent 60e053d commit f9d9c35

File tree

3 files changed

+140
-72
lines changed

3 files changed

+140
-72
lines changed

test/all_layout_annotations_test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
var domainRefTests = require('./domain_ref_shapes_test');
2+
domainRefTests.runAnnotationTests(
3+
{start:8,stop:9},
4+
);
5+

test/domain_ref_shapes_test.js

Lines changed: 133 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,15 @@ function aroSetCommonParams(aro, coordletter, axref, value) {
8484
// images take xsize, ysize, xanchor, yanchor (sizing is set to stretch for simplicity
8585
// in computing the bounding box and source is something predetermined)
8686
function aroFromParams(arotype, x0, y0, xref, yref, color, opts) {
87-
var aro = {};
8887
// fill with common values
89-
aroSetCommonParams(aro, 'x', xref, x0);
90-
aroSetCommonParams(aro, 'y', yref, y0);
88+
var aro = {
89+
xref: xref,
90+
yref: yref
91+
};
9192
switch (arotype) {
9293
case 'shape':
94+
aro.x0 = x0;
95+
aro.y0 = y0;
9396
aro.x1 = opts.x1;
9497
aro.y1 = opts.y1;
9598
aro.type = opts.type;
@@ -98,6 +101,8 @@ function aroFromParams(arotype, x0, y0, xref, yref, color, opts) {
98101
};
99102
break;
100103
case 'annotation':
104+
aro.x = x0;
105+
aro.y = y0;
101106
aro.text = "A";
102107
aro.ax = opts.ax;
103108
aro.ay = opts.ay;
@@ -108,6 +113,8 @@ function aroFromParams(arotype, x0, y0, xref, yref, color, opts) {
108113
aro.arrowcolor = color;
109114
break;
110115
case 'image':
116+
aro.x = x0;
117+
aro.y = y0;
111118
aro.sizex = opts.sizex;
112119
aro.sizey = opts.sizey;
113120
aro.xanchor = opts.xanchor;
@@ -132,10 +139,10 @@ function setAxType(layout, axref, axtype) {
132139
function annaxscale(ac, axistype, c0, K) {
133140
var ret;
134141
if (axistype === 'log') {
135-
ret = Math.pow(10, Math.log10(x0) + 2 * (Math.log10(ax) - Math.log10(
136-
x0)));
142+
ret = Math.pow(10, Math.log10(c0) + 2 * (Math.log10(ac) - Math.log10(
143+
c0)));
137144
} else {
138-
ret = x0 + 2 * (ax - x0);
145+
ret = c0 + 2 * (ac - c0);
139146
}
140147
return ret;
141148
}
@@ -149,20 +156,23 @@ function annaxscale(ac, axistype, c0, K) {
149156
// xaxistype can be linear|log, only used if xref has type 'range' or 'domain',
150157
// same for yaxistype and yref
151158
function annotationTest(gd, layout, x0, y0, ax, ay, xref, yref, axref, ayref,
152-
xaxistype, yaxistype) {
159+
xaxistype, yaxistype, xid, yid) {
153160
// if xref != axref or axref === 'pixel' then ax is a value relative to
154161
// x0 but in pixels. Same for yref
155162
var xreftype = Axes.getRefType(xref);
156163
var yreftype = Axes.getRefType(yref);
157164
var axpixels = false;
158-
var xaxname;
159-
var yaxname;
160-
if (xreftype != 'paper') {
161-
setAxType(layout, xref, xaxistype);
165+
if ((axref === 'pixel') || (Axes.getRefType(axref) != xreftype)) {
166+
axpixels = true;
162167
}
163-
if (yreftype != 'paper') {
164-
setAxType(layout, yref, yaxistype);
168+
var aypixels = false;
169+
if ((ayref === 'pixel') || (Axes.getRefType(ayref) != yreftype)) {
170+
aypixels = true;
165171
}
172+
var xaxname;
173+
var yaxname;
174+
logAxisIfAxType(gd.layout, layout, xid, xaxistype);
175+
logAxisIfAxType(gd.layout, layout, yid, yaxistype);
166176
var xpixels;
167177
var ypixels;
168178
var opts0 = {
@@ -183,42 +193,50 @@ function annotationTest(gd, layout, x0, y0, ax, ay, xref, yref, axref, ayref,
183193
var anno0 = aroFromParams('annotation', x0, y0, xref, yref, color0, opts0);
184194
var anno1 = aroFromParams('annotation', x0, y0, xref, yref, color1, opts1);
185195
layout.annotations = [anno0, anno1];
186-
Plotly.relayout(gd, layout);
187-
// the choice of anno1 or anno0 is arbitrary
188-
var xabspixels = mapAROCoordToPixel(gd.layout, xref, anno1, 'x0');
189-
var yabspixels = mapAROCoordToPixel(gd.layout, yref, anno1, 'y0');
190-
if ((axref === 'pixel') || (Axes.getRefType(axref) != xreftype)) {
191-
axpixels = true;
192-
// no need to map the specified values to pixels (because that's what
193-
// they are already)
194-
xpixels = ax;
195-
} else {
196-
axpixels = false;
197-
xpixels = mapAROCoordToPixel(gd.layout, xref, anno0, 'ax') -
198-
-xabspixels;
199-
}
200-
if ((ayref === 'pixel') || (Axes.getRefType(ayref) != yreftype)) {
201-
aypixels = true;
202-
// no need to map the specified values to pixels (because that's what
203-
// they are already)
204-
ypixels = ay;
205-
} else {
206-
aypixels = false;
207-
ypixels = mapAROCoordToPixel(gd.layout, yref, anno0, 'ay') -
208-
-yabspixels;
209-
}
210-
var annobbox0 = getSVGElemScreenBBox(findAROByColor(color0,"#"+gd.id));
211-
var annobbox1 = getSVGElemScreenBBox(findAROByColor(color1,"#"+gd.id));
212-
// solve for the arrow length's x coordinate
213-
var arrowLenX = ((annobbox1.x + annobbox1.width) - (annobbox0.x + annobbox0
214-
.width));
215-
// SVG's y is the top of the box, so no need to offset by height
216-
var arrowLenY = annobbox1.y - annobbox0.y;
217-
var ret = coordsEq(arrowLenX, xpixels) &&
218-
coordsEq(arrowLenY, ypixels) &&
219-
coordsEq(xabspixels, annobbox0.x) &&
220-
coordsEq(yabspixels, annobbox0.y + annobbox0.height);
221-
return ret;
196+
return Plotly.relayout(gd, layout).then(function (gd) {
197+
// the choice of anno1 or anno0 is arbitrary
198+
var xabspixels = mapAROCoordToPixel(gd.layout, 'xref', anno1, 'x');
199+
var yabspixels = mapAROCoordToPixel(gd.layout, 'yref', anno1, 'y');
200+
if (axpixels) {
201+
// no need to map the specified values to pixels (because that's what
202+
// they are already)
203+
xpixels = ax;
204+
} else {
205+
xpixels = mapAROCoordToPixel(gd.layout, 'xref', anno0, 'ax') -
206+
xabspixels;
207+
}
208+
if (aypixels) {
209+
// no need to map the specified values to pixels (because that's what
210+
// they are already)
211+
ypixels = ay;
212+
} else {
213+
ypixels = mapAROCoordToPixel(gd.layout, 'yref', anno0, 'ay') -
214+
yabspixels;
215+
}
216+
var annobbox0 = getSVGElemScreenBBox(findAROByColor(color0,"#"+gd.id));
217+
var annobbox1 = getSVGElemScreenBBox(findAROByColor(color1,"#"+gd.id));
218+
// solve for the arrow length's x coordinate
219+
var arrowLenX = ((annobbox1.x + annobbox1.width) - (annobbox0.x + annobbox0
220+
.width));
221+
var arrowLenY;
222+
var yabspixelscmp;
223+
if (aypixels) {
224+
// for annotations whose arrows are specified in relative pixels,
225+
// positive pixel values on the y axis mean moving down the page like
226+
// SVG coordinates, so we have to add height
227+
var arrowLenY = (annobbox1.y + annobbox1.height)
228+
- (annobbox0.y + annobbox0.height);
229+
yabspixelscmp = annobbox0.y;
230+
} else {
231+
var arrowLenY = annobbox1.y - annobbox0.y;
232+
yabspixelscmp = annobbox0.y + annobbox0.height;
233+
}
234+
var ret = coordsEq(arrowLenX, xpixels) &&
235+
coordsEq(arrowLenY, ypixels) &&
236+
coordsEq(xabspixels, annobbox0.x) &&
237+
coordsEq(yabspixels, yabspixelscmp);
238+
return ret;
239+
});
222240
}
223241

224242
// axid is e.g., 'x', 'y2' etc.
@@ -341,7 +359,7 @@ function compareBBoxes(a, b) {
341359
function findAROByColor(color,id) {
342360
id = (id === undefined) ? '' : id + ' ';
343361
var selector = id + 'path';
344-
var ret = d3.selectAll(id).filter(function() {
362+
var ret = d3.selectAll(selector).filter(function() {
345363
return this.style.stroke === color;
346364
}).node();
347365
return ret;
@@ -350,7 +368,7 @@ function findAROByColor(color,id) {
350368
function findImage(id) {
351369
id = (id === undefined) ? '' : id + ' ';
352370
var selector = id + 'g image';
353-
var ret = d3.select('g image').node();
371+
var ret = d3.select(selector).node();
354372
return ret;
355373
}
356374

@@ -541,6 +559,19 @@ function test_correct_aro_positions() {
541559
testCombos.forEach(testDomRefAROCombo);
542560
}
543561

562+
function runComboTests(productItems,testCombo,start_stop,filter) {
563+
var testCombos = [...iterable.cartesianProduct(productItems)];
564+
testCombos=testCombos.map((c,i)=>c.concat(['graph-'+i]));
565+
if(filter) {
566+
testCombos=testCombos.filter(filter);
567+
}
568+
if(start_stop) {
569+
testCombos=testCombos.slice(start_stop.start,start_stop.stop);
570+
}
571+
console.log("Executing " + testCombos.length + " tests");
572+
var tc = testCombos.map(c=>testCombo(c,false)).reduce((a,v)=>a.then(v));
573+
}
574+
544575
var testImageComboMock = Lib.extendDeep({},
545576
require('../test/image/mocks/domain_ref_base.json'));
546577

@@ -580,7 +611,6 @@ function testImageCombo(combo,keep_graph_div) {
580611
"yref:", yref, "\n",
581612
].join(' '), test_ret);
582613
}).then( function () {
583-
console.log("Hello?", keep_graph_div);
584614
if (!keep_graph_div) {
585615
console.log('destroying graph div ', gd_id);
586616
Plotly.purge(gd_id);
@@ -590,37 +620,70 @@ function testImageCombo(combo,keep_graph_div) {
590620
}
591621

592622
function runImageTests(start_stop,filter) {
593-
var testCombos = [...iterable.cartesianProduct([
623+
runComboTests([
594624
axisTypes, axisTypes, axisPairs,
595625
// axis reference types are contained in here
596626
aroPositionsX, aroPositionsY,
597627
xAnchors, yAnchors
598-
])];
599-
// add a unique id to each combination so we can instantiate a unique graph
600-
// each time
601-
testCombos=testCombos.map((c,i)=>c.concat(['graph-'+i]));
602-
if(filter) {
603-
testCombos=testCombos.filter(filter);
604-
}
605-
if(start_stop) {
606-
testCombos=testCombos.slice(start_stop.start,start_stop.stop);
607-
}
608-
console.log("Executing " + testCombos.length + " tests");
609-
var tc = testCombos.map(c=>testImageCombo(c,false)).reduce((a,v)=>a.then(v));
628+
],testImageCombo,start_stop,filter);
610629
}
611630

612-
function testAnnotationCombo(combo) {
631+
function testAnnotationCombo(combo,keep_graph_div) {
613632
var axistypex = combo[0];
614633
var axistypey = combo[1];
615634
var axispair = combo[2];
616635
var aroposx = combo[3];
617636
var aroposy = combo[4];
618-
var xanchor = combo[5];
619-
var yanchor = combo[6];
620-
var gd_id = combo[7];
637+
var arrowaxispair = combo[5];
638+
var gd_id = combo[6];
639+
var xid = axispair[0];
640+
var yid = axispair[1];
641+
var xref = makeAxRef(xid, aroposx.ref);
642+
var yref = makeAxRef(yid, aroposy.ref);
643+
var axref = arrowaxispair[0] === 'p' ? 'pixel' : xref;
644+
var ayref = arrowaxispair[1] === 'p' ? 'pixel' : yref;
645+
var x0 = aroposx.value[0];
646+
var y0 = aroposy.value[0];
647+
var ax = axref === 'pixel' ? aroposx.pixel : aroposx.value[1];
648+
var ay = ayref === 'pixel' ? aroposy.pixel : aroposy.value[1];
649+
if (DEBUG) {
650+
console.log(combo);
651+
}
652+
return new Promise(function(resolve){
653+
var gd = createGraphDiv(gd_id);
654+
resolve(gd);
655+
}).then(function (gd) { return Plotly.newPlot(gd, testImageComboMock); })
656+
.then(function (gd) {
657+
return annotationTest(gd, {}, x0, y0, ax, ay, xref, yref, axref,
658+
ayref, axistypex, axistypey, xid, yid);
659+
}).then( function (test_ret) {
660+
console.log([
661+
"Testing layout annotation " + gd_id + " with parameters:",
662+
"x-axis type:", axistypex, "\n",
663+
"y-axis type:", axistypey, "\n",
664+
"arrow axis pair:", arrowaxispair, "\n",
665+
"xref:", xref, "\n",
666+
"yref:", yref, "\n",
667+
].join(' '), test_ret);
668+
}).then( function () {
669+
if (!keep_graph_div) {
670+
console.log('destroying graph div ', gd_id);
671+
Plotly.purge(gd_id);
672+
destroyGraphDiv(gd_id);
673+
}
674+
});
675+
}
676+
677+
function runAnnotationTests(start_stop,filter) {
678+
runComboTests([
679+
axisTypes, axisTypes, axisPairs, aroPositionsX, aroPositionsY, arrowAxis
680+
],
681+
testAnnotationCombo,start_stop,filter);
621682
}
622683

623684
module.exports = {
624685
runImageTests: runImageTests,
625-
testImageCombo: testImageCombo
686+
testImageCombo: testImageCombo,
687+
runAnnotationTests: runAnnotationTests,
688+
testAnnotationCombo: testAnnotationCombo
626689
};

test/image/mocks/domain_ref_base.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"range": [1, 3]
2222
},
2323
"yaxis": {
24-
"domain": [0,.4],
24+
"domain": [0,0.4],
2525
"range": [1, 4]
2626
},
2727
"xaxis2": {
@@ -30,7 +30,7 @@
3030
"anchor": "y2"
3131
},
3232
"yaxis2": {
33-
"domain": [.4,1],
33+
"domain": [0.4,1],
3434
"range": [1, 3],
3535
"anchor": "x2"
3636
},

0 commit comments

Comments
 (0)