Skip to content

Improved category axes conversions #1748

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 8 commits into from
May 31, 2017
Merged

Conversation

etpinard
Copy link
Contributor

@etpinard etpinard commented May 30, 2017

fixes #1720

This PR is a rebased version of the component-category-axes-relayout-attempt branch with better commit messages.

In brief, category (i.e. string) values of annotation/shape/image position attributes (e.g. x, y, x0 ...) referencing type: 'category' axes are no longer converted to indices (i.e. numbers) during the defaults step. This implies:

etpinard added 5 commits May 30, 2017 17:30
... in Plots.doCalcdata

- this approach was flawed: led to position value not updating
  properly on calc-less update (e.g. zoom/pan)
- DO NOT convert category position value to indices (the old 'r')
  in Axes.coercePosition - as this relied on ax._categories which
  isn't defined during Plots.supplyDefaults.
- modify `type: 'category'` conversions functions accordingly (a bit hacky)
- update annotation/click.js to reflect change in 'r' definition
- use ax.cleanPos to clean position value per axis type in coercePosition
- as now Axes.coercePosition does not rely on
  ax._categories for `type: 'category' axes.
- a little wrapper around ax.cleanPos
- use it for annotations *xclick* and *yclick*
@etpinard etpinard added status: reviewable bug something broken labels May 30, 2017
@etpinard etpinard added this to the 1.28.0 milestone May 30, 2017
src/lib/index.js Outdated
@@ -87,6 +92,13 @@ lib.pushUnique = require('./push_unique');

lib.cleanNumber = require('./clean_number');

lib.num = function num(v) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we want a more descriptive name for this now that it's not just internal to one module? ensureNumber? safeNumber?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I went with ensureNumber in 071249f


if(axRef === 'paper' || axRef === 'pixel') {
ax = { cleanPos: Lib.num };
Copy link
Collaborator

Choose a reason for hiding this comment

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

don't need to pretend we're making an axis anymore... just cleanPos = Lib.num or cleanPos = ax.cleanPos

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done in 071249f

if(hasColumns(trace)) {
convertColumnData(trace, xa, ya, 'x', 'y', ['z']);
x = trace.x;
y = trace.y;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh interesting... were we double-converting triplet data on category and date axes before? Do we have a test of these cases?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

were we double-converting triplet

Right. Previously ax.d2c was called twice in heatmap/calc.js. For example, on master the heatmap_xyz-dates-and-categories mock has:

gd._fullLayout.yaxis._categories
// ["3-month", "6-month", "1-year", "2-year", "3-year", "5-year", 0, 1, 2, 3, 4, 5]

which still gives the correct result though as the string categories are ignored during r2p.

Now that, starting in this PR, r2p convert strings to pixels, this patch is now necessary to make the heatmap_xyz-dates-and-categories pass.

Do we have a test of these cases?

Good call. I added heatmap/calc test case to 🔒 this down more explicitly in 4434fad

expect(layoutOut.annotations[1]._xclick).toBe(1, 'linear');
expect(layoutOut.annotations[1]._yclick).toBe(undefined, 'invalid date');
expect(layoutOut.annotations[2]._xclick).toBe(2, 'log');
expect(layoutOut.annotations[2]._yclick).toBe('A', 'category');
Copy link
Collaborator

Choose a reason for hiding this comment

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

🎉

it('should handle the category x/y/z/ column case', function() {
var out = _calc({
x: ['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c'],
y: ['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C'],
Copy link
Collaborator

Choose a reason for hiding this comment

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

can we test dates too? That's the other case where d2c shouldn't be called multiple times - actually, that results in a timezone shift because of our legacy support for local milliseconds!

ax.d2c('1970-01-02')
86400000
ax.d2c(ax.d2c('1970-01-02'))
68400000
ax.d2c(ax.d2c(ax.d2c('1970-01-02')))
50400000

Copy link
Contributor Author

Choose a reason for hiding this comment

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

➡️ 0fafe14

@alexcjohnson
Copy link
Collaborator

Looks great! Thanks for the tweaks.
💃

@etpinard etpinard merged commit e37eeae into master May 31, 2017
@etpinard etpinard deleted the better-category-axes-conversions branch May 31, 2017 18:58
etpinard added a commit that referenced this pull request Jun 16, 2017
- same as what Axes.coercePosition does at the defaults step
  for other axis types
- post #1748, we need to handle this at the ax.r2c as the categories
  are only known after the calc step.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something broken
Projects
None yet
Development

Successfully merging this pull request may close these issues.

shapes on category axis are redrawn incorrectly after zoom
2 participants