Skip to content
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

Polar 2.0 #2200

Merged
merged 73 commits into from
Jan 16, 2018
Merged
Changes from 1 commit
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
58d53e8
move (old) polar code to legacy/ folder
etpinard Nov 20, 2017
853581e
introduce scatterpolar attributes
etpinard Dec 11, 2017
3c8ae5b
introduce polar subplot attributes
etpinard Dec 11, 2017
ca8081b
introduce angles helper module
etpinard Dec 11, 2017
46fe066
first cut polar subplot defaults and draw routines
etpinard Dec 11, 2017
0826ee7
first cut scatterpolar calc/defaults/plot/style/hover
etpinard Dec 11, 2017
9770f2c
misc things to get scatterpolar traces to show up
etpinard Dec 11, 2017
0b85af2
init categories stashes for polar axes
etpinard Dec 11, 2017
cbf19c1
allow ticksuffix dflt to be passed via option
etpinard Dec 11, 2017
86204a6
get polar axis updates to work
etpinard Dec 11, 2017
0027f53
add legacy deprecation warnings
etpinard Dec 11, 2017
4cdc301
remove obsolete check for polar in registry
etpinard Dec 11, 2017
a5a719c
get snapshot redraw function right for (new) polar
etpinard Dec 11, 2017
da720aa
improve scatterpolar hover
etpinard Dec 11, 2017
04a886b
use subplot ref in scatterternary hover pointData
etpinard Dec 11, 2017
22cf4ba
expose a few things out of cartesian dragbox for :recycle:
etpinard Dec 11, 2017
122dd0b
uber wip polar main drag interaction
etpinard Dec 11, 2017
689414c
add radial axis drag interactions
etpinard Dec 11, 2017
543b615
first cut polar mocks!
etpinard Dec 11, 2017
54b3f1c
Merge branch 'master' into polar
etpinard Dec 15, 2017
17503cb
make scatter{ternary,polar,carpet} Scatter.style reuse straight-up
etpinard Dec 14, 2017
7b0f718
add test for commit 86204a6 (ternary ax tickfont relayouts)
etpinard Dec 14, 2017
fbea869
:palm_tree: domain attributes
etpinard Dec 14, 2017
1e769f0
make non-zero radialaxis.range[0] work
etpinard Dec 14, 2017
f53495e
make radial/angular axis visible: false cases work
etpinard Dec 14, 2017
c5a3a72
1st pass isPtWithinSector algo
etpinard Dec 15, 2017
61e155c
warn -> log for polar deprecation
etpinard Dec 15, 2017
258600d
:hocho: special polygon logic from scatterpolar/plot
etpinard Dec 18, 2017
0a41da5
implement {angular,radial}axis.layer
etpinard Dec 18, 2017
f3a2379
:palm_tree: make filter-visible work for calcdata containers
etpinard Dec 19, 2017
3f5e77b
first cut radial axis drag intractions
etpinard Dec 19, 2017
65b717d
get `polar.sector` working on category angular axes
etpinard Dec 19, 2017
13568a3
fixup isPtWithinSector
etpinard Dec 20, 2017
797fec1
add support for 'log' radial axes
etpinard Dec 20, 2017
0a9278c
fixup axis autotype logic for visible: false traces
etpinard Dec 22, 2017
07a3af7
make sure that angular setting relayout call propagate to tick labels
etpinard Dec 22, 2017
a263c1c
solid zoombox try + some pan work and radial drag fixups
etpinard Dec 22, 2017
765d2b7
pretty solid zoom/pan interactions
etpinard Dec 23, 2017
909d134
make polar ticks relayout more robust
etpinard Dec 27, 2017
3e1e4dd
:palm_tree: calcMarkerSize logic
etpinard Dec 28, 2017
a96131d
fix hoveron fill hover label placement edge case
etpinard Dec 28, 2017
b35d7ec
update ticks when panning sectors using new wrap180 routine
etpinard Dec 28, 2017
5751de5
make marker.size bump radial autorange results
etpinard Dec 28, 2017
86067a6
:palm_tree: cartesian/ternary/polar line/grid default logic
etpinard Dec 29, 2017
5422da9
coerce 'cliponaxis' only when markers and/or text are present
etpinard Dec 29, 2017
b4af46f
clear ternary axis titles when ternary subplots are removed
etpinard Jan 3, 2018
20b17e5
set radialaxis.rangemode dflt to 'tozero' + add support for -ve r ranges
etpinard Jan 4, 2018
cb78d19
implement radialaxis.title
etpinard Jan 4, 2018
25b4e7b
even more robust relayout
etpinard Jan 4, 2018
1e81039
large commit of attribute name & dflt changes
etpinard Jan 4, 2018
e5d238d
remove crispEdges for all polar subplot paths
etpinard Jan 4, 2018
0146c2f
Merge branch 'master' into polar
etpinard Jan 4, 2018
c94423b
adapt polar to clean-subplots improvements
etpinard Jan 4, 2018
4d5a1bd
fixups for domain attrs
etpinard Jan 10, 2018
d4c7d2c
default *rotation* to 90 for clockwise *direction*
etpinard Jan 10, 2018
8b4c2b5
do not implement 'date' angular axes (for now)
etpinard Jan 10, 2018
5357501
clear polar radial range viewInitial during log <-> linear relayout
etpinard Jan 10, 2018
9a71ba3
set limit of 100 for num2frac denominator
etpinard Jan 10, 2018
f714449
extend line & fills to polar center when pts < radialaxis.range[0]
etpinard Jan 10, 2018
cde7369
fixup radial axis drag rotate logic
etpinard Jan 10, 2018
9c4c9bf
Merge branch 'master' into polar
etpinard Jan 11, 2018
b365374
more strict check for polar subplot existence
etpinard Jan 11, 2018
a72ce55
adapt polar main drag to dragElement updates (+ tests)
etpinard Jan 11, 2018
473643c
AJ-proof latest additions
etpinard Jan 12, 2018
c2da23e
replace dragmode: 'pan' with annulus-shaped dragger
etpinard Jan 11, 2018
974740b
improve zoom dragbox behavior
etpinard Jan 11, 2018
e8aec86
un-rotate markers and text pts during angular drag
etpinard Jan 12, 2018
e8865bc
add scatterpolar hover label tests
etpinard Dec 22, 2017
8a33b89
add scatterpolar select test
etpinard Jan 12, 2018
c7a7f59
add polar drag interaction tests
etpinard Jan 15, 2018
7f7193d
a few small tweaks
etpinard Jan 15, 2018
816be51
misc. polar fixup after AJ's review:
etpinard Jan 16, 2018
18a3a0d
add clampFn option to dragElement & use it for radial drag box
etpinard Jan 16, 2018
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
327 changes: 327 additions & 0 deletions src/plots/polar/layout_attributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
/**
* Copyright 2012-2017, 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 colorAttrs = require('../../components/color/attributes');
var axesAttrs = require('../cartesian/layout_attributes');
var extendFlat = require('../../lib').extendFlat;
var overrideAll = require('../../plot_api/edit_types').overrideAll;

var domainItem = {
valType: 'info_array',
role: 'info',
editType: 'plot',
items: [
{valType: 'number', min: 0, max: 1},
{valType: 'number', min: 0, max: 1}
],
dflt: [0, 1]
};

var axisLineGridAttr = overrideAll({
color: axesAttrs.color,
showline: extendFlat({}, axesAttrs.showline, {dflt: true}),
linecolor: axesAttrs.linecolor,
linewidth: axesAttrs.linewidth,
showgrid: extendFlat({}, axesAttrs.showgrid, {dflt: true}),
gridcolor: axesAttrs.gridcolor,
gridwidth: axesAttrs.gridwidth

// should we add zeroline* attributes?
// might be useful on radial axes where range is negative and positive

// we could add spike* attributes down the road
}, 'plot', 'from-root');

var axisTickAttr = overrideAll({
tickmode: axesAttrs.tickmode,
nticks: axesAttrs.nticks,
tick0: axesAttrs.tick0,
dtick: axesAttrs.dtick,
tickvals: axesAttrs.tickvals,
ticktext: axesAttrs.ticktext,
ticks: axesAttrs.ticks,
ticklen: axesAttrs.ticklen,
tickwidth: axesAttrs.tickwidth,
tickcolor: axesAttrs.tickcolor,
showticklabels: axesAttrs.showticklabels,
showtickprefix: axesAttrs.showtickprefix,
tickprefix: axesAttrs.tickprefix,
showticksuffix: axesAttrs.showticksuffix,
ticksuffix: axesAttrs.ticksuffix,
showexponent: axesAttrs.showexponent,
exponentformat: axesAttrs.exponentformat,
separatethousands: axesAttrs.separatethousands,
tickfont: axesAttrs.tickfont,
tickangle: axesAttrs.tickangle,
tickformat: axesAttrs.tickformat,
tickformatstops: axesAttrs.tickformatstops,
}, 'plot', 'from-root');

var radialAxisAttrs = {
visible: extendFlat({}, axesAttrs.visible, {dflt: true}),
type: axesAttrs.type,

// You thought maybe that range should only be a 'max' instead
// as it always starts at 0? But, looks like off-zero cutout polar chart are
// a thing:
// -> mpl allow radial ranges to start off 0
// -> same for matlab: https://www.mathworks.com/help/matlab/ref/rlim.html
Copy link
Contributor Author

Choose a reason for hiding this comment

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

e.g. in matlab:

image

autorange: axesAttrs.autorange,
// might make 'nonnegative' the default,
// or add a special polar algo.
rangemode: axesAttrs.rangemode,
range: axesAttrs.range,

categoryorder: axesAttrs.categoryorder,
categoryarray: axesAttrs.categoryarray,

// position (name analogous to xaxis.position),
// or maybe something more specific e.g. angle angleoffset?
//
// (should this support any data coordinate system?)
// I think it is more intuitive to set this as just an angle!
// Thoughts?
position: {
valType: 'angle',
editType: 'plot',
role: 'info',
description: [
'Sets the angle (in degrees) from which the radial axis is drawn.',
'Note that by default, radial axis line on the theta=0 line',
'corresponds to a line pointing right (like what mathematicians prefer).',
'Defaults to the first `polar.sector` angle.'
].join(' ')
},

side: {
valType: 'enumerated',
// maybe 'clockwise' and 'counterclockwise' would be best here
values: ['left', 'right'],
dflt: 'right',
editType: 'plot',
role: 'info',
description: [
'Determines on which side of radial axis line',
'the tick and tick labels appear.'
].join(' ')
},

// not sure about these
// maybe just for radialaxis ??
title: axesAttrs.title,
titlefont: axesAttrs.titlefont,

// only applies to radial axis for now (i.e. for cliponaxis: false traces)
// but angular.layer could be a thing later
layer: axesAttrs.layer,

hoverformat: axesAttrs.hoverformat,

// More attributes:

// We'll need some attribute that determines the span
// to draw donut-like charts
// e.g. https://github.com/matplotlib/matplotlib/issues/4217
//
// maybe something like 'span' or 'hole' (like pie, but pie set it in data coords?)
// span: {},
// hole: 1

// maybe should add a boolean to enable square grid lines
// and square axis lines
// (most common in radar-like charts)
// e.g. squareline/squaregrid or showline/showgrid: 'square' (on-top of true)

editType: 'calc'
};

extendFlat(
radialAxisAttrs,

// N.B. the radialaxis grid lines are circular,
// but radialaxis lines are straight from circle center to outer bound
axisLineGridAttr,
axisTickAttr
);

var angularAxisAttrs = {
visible: extendFlat({}, axesAttrs.visible, {dflt: true}),
type: {
valType: 'enumerated',
// 'linear' should maybe be called 'angle' or 'angular' here
// to make clear that axis here is periodic and more tightly match
// `thetaunit`?
//
// no 'log' for now
values: ['-', 'linear', 'date', 'category'],
dflt: '-',
role: 'info',
editType: 'calc',
description: [
'Sets the angular axis type.',
'If *linear*, set `thetaunit` to determine the unit in which axis value are shown.',
'If *date*, set `period` to determine the wrap around period.',
'If *category, set `period` to determine the number of integer coordinates around polar axis.'
].join(' ')
},

categoryorder: axesAttrs.categoryorder,
categoryarray: axesAttrs.categoryarray,

thetaunit: {
valType: 'enumerated',
values: ['radians', 'degrees'],
dflt: 'degrees',
role: 'info',
editType: 'calc',
description: [
'Sets the format unit of the formatted *theta* values.',
'Has an effect only when `angularaxis.type` is *linear*.'
].join(' ')
},

period: {
valType: 'any',
editType: 'calc',
role: 'info',
description: ''

// 360 / 2*pi for linear (might not need to set it)
// and to full range for other types

// 'period' is the angular equivalent to 'range'

// similar to dtick, one way to achieve e.g.:
// - period that equals the timeseries length
// http://flowingdata.com/2017/01/24/one-dataset-visualized-25-ways/18-polar-coordinates/
// - and 1-year periods (focusing on seasonal change0
// http://otexts.org/fpp2/seasonal-plots.html
// https://blogs.scientificamerican.com/sa-visual/why-are-so-many-babies-born-around-8-00-a-m/
// http://www.seasonaladjustment.com/2012/09/05/clock-plot-visualising-seasonality-using-r-and-ggplot2-part-3/
// https://i.pinimg.com/736x/49/b9/72/49b972ccb3206a1a6d6f870dac543280.jpg
// https://www.climate-lab-book.ac.uk/spirals/
},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Some screenshot of date angular axes:

image

image

image

image

Copy link

Choose a reason for hiding this comment

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

Great feature !! Can you please include the code (layout config attributes) for the above example screenshots?


direction: {
valType: 'enumerated',
values: ['counterclockwise', 'clockwise'],
// we could make the default 'clockwise' for date axes ...
dflt: 'counterclockwise',
role: 'info',
editType: 'calc',
description: [
'Sets the direction corresponding to positive angles.'
].join(' ')
},

// matlab uses thetaZeroLocation: 'North', 'West', 'East', 'South'
// mpl uses set_theta_zero_location('W', offset=10)
//
// position is analogous to yaxis.position, but as an angle (going
// counterclockwise about cartesian y=0.
position: {
valType: 'angle',
// we could maybe make `position: 90` by default for category and date angular axes.
dflt: 0,
editType: 'calc',
role: 'info',
description: [
'Sets that start position (in degrees) of the angular axis',
'Note that by default, polar subplots are orientation such that the theta=0',
'corresponds to a line pointing right (like what mathematicians prefer).',
'For example to make the angular axis start from the North (like on a compass),',
'set `angularaxis.position` to *90*.'
].join(' ')
},

hoverformat: axesAttrs.hoverformat,

editType: 'calc'
};

extendFlat(
angularAxisAttrs,

// N.B. the angular grid lines are straight lines from circle center to outer bound
// the angular line is circular bounding the polar plot area.
axisLineGridAttr,
// Note that ticksuffix defaults to '°' for angular axes with `thetaunit: 'degrees'`
axisTickAttr
);

module.exports = {
// AJ and I first thought about a x/y/zoom system for paper-based zooming
// but I came to think that sector span + radial axis range
// zooming will be better
//
// TODO confirm with team.
// x: {},
// y: {},
// zoom: {},

domain: {
x: extendFlat({}, domainItem, {
description: [
'Sets the horizontal domain of this subplot',
'(in plot fraction).'
].join(' ')
}),
y: extendFlat({}, domainItem, {
description: [
'Sets the vertical domain of this subplot',
'(in plot fraction).'
].join(' ')
}),
editType: 'plot'
},

// Maybe this should angularaxis.range correspond to
// angular span of the drawing area?
//
// matlab's angular equivalent to 'range' bounds the drawing area
// (partial circles as they call it)
// https://www.mathworks.com/help/matlab/ref/thetalim.html
//
// as this attribute would be best set in (absolute) angles,
// I think this should be set outside of angularaxis e.g
// as polar.sector: [0, 180]
sector: {
valType: 'info_array',
items: [
// or be more strict -> `valType: 'angle' with `dflt: [0, 360]`
{valType: 'number', editType: 'plot'},
{valType: 'number', editType: 'plot'}
],
dflt: [0, 360],
role: 'info',
editType: 'plot',
description: [
'Sets angular span of this polar subplot with two angles (in degrees).',
'Sector are assumed to be spanned in the counterclockwise direction',
'with *0* corresponding to rightmost limit of the polar subplot.'
].join(' ')
},

bgcolor: {
valType: 'color',
role: 'style',
editType: 'plot',
dflt: colorAttrs.background,
description: 'Set the background color of the subplot'
},

radialaxis: radialAxisAttrs,
angularaxis: angularAxisAttrs,

// TODO maybe?
// annotations:

editType: 'calc'
};