Skip to content

Commit 56e0a97

Browse files
authored
Merge pull request #5615 from arclamp/smith
Add a basic smith chart
2 parents 642c034 + c1613b2 commit 56e0a97

35 files changed

+6054
-944
lines changed

Diff for: lib/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Plotly.register([
5050
require('./scatterpolar'),
5151
require('./scatterpolargl'),
5252
require('./barpolar'),
53+
require('./scattersmith'),
5354

5455
// transforms
5556
require('./aggregate'),

Diff for: lib/scattersmith.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
3+
module.exports = require('../src/traces/scattersmith');

Diff for: src/plot_api/plot_api.js

+3
Original file line numberDiff line numberDiff line change
@@ -3729,6 +3729,9 @@ function makePlotFramework(gd) {
37293729
// single polar layer for the whole plot
37303730
fullLayout._polarlayer = fullLayout._paper.append('g').classed('polarlayer', true);
37313731

3732+
// single smith layer for the whole plot
3733+
fullLayout._smithlayer = fullLayout._paper.append('g').classed('smithlayer', true);
3734+
37323735
// single ternary layer for the whole plot
37333736
fullLayout._ternarylayer = fullLayout._paper.append('g').classed('ternarylayer', true);
37343737

Diff for: src/plots/smith/constants.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use strict';
2+
3+
module.exports = {
4+
attr: 'subplot',
5+
name: 'smith',
6+
7+
axisNames: ['imaginaryaxis', 'realaxis'],
8+
axisName2dataArray: {imaginaryaxis: 'theta', realaxis: 'r'},
9+
10+
layerNames: [
11+
'draglayer',
12+
'plotbg',
13+
'angular-grid',
14+
'radial-grid',
15+
'frontplot',
16+
'angular-line',
17+
'radial-line',
18+
'angular-axis',
19+
'radial-axis'
20+
],
21+
};

Diff for: src/plots/smith/index.js

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
'use strict';
2+
3+
var getSubplotCalcData = require('../get_data').getSubplotCalcData;
4+
var counterRegex = require('../../lib').counterRegex;
5+
6+
var createSmith = require('./smith');
7+
var constants = require('./constants');
8+
9+
var attr = constants.attr;
10+
var name = constants.name;
11+
var counter = counterRegex(name);
12+
13+
var attributes = {};
14+
attributes[attr] = {
15+
valType: 'subplotid',
16+
dflt: name,
17+
editType: 'calc',
18+
description: [
19+
'Sets a reference between this trace\'s data coordinates and',
20+
'a smith subplot.',
21+
'If *smith* (the default value), the data refer to `layout.smith`.',
22+
'If *smith2*, the data refer to `layout.smith2`, and so on.'
23+
].join(' ')
24+
};
25+
26+
function plot(gd) {
27+
var fullLayout = gd._fullLayout;
28+
var calcData = gd.calcdata;
29+
var subplotIds = fullLayout._subplots[name];
30+
31+
for(var i = 0; i < subplotIds.length; i++) {
32+
var id = subplotIds[i];
33+
var subplotCalcData = getSubplotCalcData(calcData, name, id);
34+
var subplot = fullLayout[id]._subplot;
35+
36+
if(!subplot) {
37+
subplot = createSmith(gd, id);
38+
fullLayout[id]._subplot = subplot;
39+
}
40+
41+
subplot.plot(subplotCalcData, fullLayout, gd._promises);
42+
}
43+
}
44+
45+
function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) {
46+
var oldIds = oldFullLayout._subplots[name] || [];
47+
48+
for(var i = 0; i < oldIds.length; i++) {
49+
var id = oldIds[i];
50+
var oldSubplot = oldFullLayout[id]._subplot;
51+
52+
if(!newFullLayout[id] && !!oldSubplot) {
53+
oldSubplot.framework.remove();
54+
oldSubplot.layers['radial-axis-title'].remove();
55+
56+
for(var k in oldSubplot.clipPaths) {
57+
oldSubplot.clipPaths[k].remove();
58+
}
59+
}
60+
}
61+
}
62+
63+
module.exports = {
64+
attr: attr,
65+
name: name,
66+
idRoot: name,
67+
idRegex: counter,
68+
attrRegex: counter,
69+
attributes: attributes,
70+
layoutAttributes: require('./layout_attributes'),
71+
supplyLayoutDefaults: require('./layout_defaults'),
72+
plot: plot,
73+
clean: clean,
74+
toSVG: require('../cartesian').toSVG
75+
};

Diff for: src/plots/smith/layout_attributes.js

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
'use strict';
2+
3+
var colorAttrs = require('../../components/color/attributes');
4+
var axesAttrs = require('../cartesian/layout_attributes');
5+
var domainAttrs = require('../domain').attributes;
6+
var extendFlat = require('../../lib').extendFlat;
7+
var overrideAll = require('../../plot_api/edit_types').overrideAll;
8+
9+
var axisLineGridAttr = overrideAll({
10+
color: axesAttrs.color,
11+
showline: extendFlat({}, axesAttrs.showline, {dflt: true}),
12+
linecolor: axesAttrs.linecolor,
13+
linewidth: axesAttrs.linewidth,
14+
showgrid: extendFlat({}, axesAttrs.showgrid, {dflt: true}),
15+
gridcolor: axesAttrs.gridcolor,
16+
gridwidth: axesAttrs.gridwidth
17+
}, 'plot', 'from-root');
18+
19+
var axisTickAttrs = overrideAll({
20+
tickmode: axesAttrs.tickmode,
21+
tickvals: axesAttrs.tickvals,
22+
ticktext: axesAttrs.ticktext,
23+
ticks: axesAttrs.ticks,
24+
ticklen: axesAttrs.ticklen,
25+
tickwidth: axesAttrs.tickwidth,
26+
tickcolor: axesAttrs.tickcolor,
27+
showticklabels: axesAttrs.showticklabels,
28+
showtickprefix: axesAttrs.showtickprefix,
29+
tickprefix: axesAttrs.tickprefix,
30+
showticksuffix: axesAttrs.showticksuffix,
31+
ticksuffix: axesAttrs.ticksuffix,
32+
showexponent: axesAttrs.showexponent,
33+
exponentformat: axesAttrs.exponentformat,
34+
minexponent: axesAttrs.minexponent,
35+
separatethousands: axesAttrs.separatethousands,
36+
tickfont: axesAttrs.tickfont,
37+
tickangle: axesAttrs.tickangle,
38+
tickformat: axesAttrs.tickformat,
39+
tickformatstops: axesAttrs.tickformatstops,
40+
layer: axesAttrs.layer
41+
}, 'plot', 'from-root');
42+
43+
var realAxisAttrs = {
44+
visible: extendFlat({}, axesAttrs.visible, {dflt: true}),
45+
46+
title: {
47+
// radial title is not gui-editable at the moment,
48+
// so it needs dflt: '', similar to carpet axes.
49+
text: extendFlat({}, axesAttrs.title.text, {editType: 'plot', dflt: ''}),
50+
font: extendFlat({}, axesAttrs.title.font, {editType: 'plot'}),
51+
52+
// TODO
53+
// - might need a 'titleside' and even 'titledirection' down the road
54+
// - what about standoff ??
55+
56+
editType: 'plot'
57+
},
58+
59+
hoverformat: axesAttrs.hoverformat,
60+
61+
uirevision: {
62+
valType: 'any',
63+
editType: 'none',
64+
description: [
65+
'Controls persistence of user-driven changes in axis `range`,',
66+
'`autorange`, `angle`, and `title` if in `editable: true` configuration.',
67+
'Defaults to `smith<N>.uirevision`.'
68+
].join(' ')
69+
},
70+
71+
editType: 'calc',
72+
};
73+
74+
extendFlat(
75+
realAxisAttrs,
76+
77+
// N.B. realaxis grid lines are circular,
78+
// but realaxis lines are straight from circle center to outer bound
79+
axisLineGridAttr,
80+
axisTickAttrs
81+
);
82+
83+
var imaginaryAxisAttrs = {
84+
visible: extendFlat({}, axesAttrs.visible, {dflt: true}),
85+
86+
direction: {
87+
valType: 'enumerated',
88+
values: ['counterclockwise', 'clockwise'],
89+
dflt: 'counterclockwise',
90+
editType: 'calc',
91+
description: [
92+
'Sets the direction corresponding to positive angles.'
93+
].join(' ')
94+
},
95+
96+
rotation: {
97+
valType: 'angle',
98+
editType: 'calc',
99+
description: [
100+
'Sets that start position (in degrees) of the angular axis',
101+
'By default, smith subplots with `direction` set to *counterclockwise*',
102+
'get a `rotation` of *0*',
103+
'which corresponds to due East (like what mathematicians prefer).',
104+
'In turn, smith with `direction` set to *clockwise* get a rotation of *90*',
105+
'which corresponds to due North (like on a compass),'
106+
].join(' ')
107+
},
108+
109+
hoverformat: axesAttrs.hoverformat,
110+
111+
uirevision: {
112+
valType: 'any',
113+
editType: 'none',
114+
description: [
115+
'Controls persistence of user-driven changes in axis `rotation`.',
116+
'Defaults to `smith<N>.uirevision`.'
117+
].join(' ')
118+
},
119+
120+
editType: 'calc'
121+
};
122+
123+
extendFlat(
124+
imaginaryAxisAttrs,
125+
126+
// N.B. angular grid lines are straight lines from circle center to outer bound
127+
// the angular line is circular bounding the smith plot area.
128+
axisLineGridAttr,
129+
130+
// N.B. ticksuffix defaults to '°' for angular axes with `thetaunit: 'degrees'`
131+
axisTickAttrs
132+
);
133+
134+
module.exports = {
135+
// TODO for x/y/zoom system for paper-based zooming:
136+
// x: {},
137+
// y: {},
138+
// zoom: {},
139+
140+
domain: domainAttrs({name: 'smith', editType: 'plot'}),
141+
142+
bgcolor: {
143+
valType: 'color',
144+
editType: 'plot',
145+
dflt: colorAttrs.background,
146+
description: 'Set the background color of the subplot'
147+
},
148+
149+
realaxis: realAxisAttrs,
150+
imaginaryaxis: imaginaryAxisAttrs,
151+
152+
uirevision: {
153+
valType: 'any',
154+
editType: 'none',
155+
description: [
156+
'Controls persistence of user-driven changes in axis attributes,',
157+
'if not overridden in the individual axes.',
158+
'Defaults to `layout.uirevision`.'
159+
].join(' ')
160+
},
161+
162+
editType: 'calc'
163+
};

0 commit comments

Comments
 (0)