Skip to content

Add "tickpadding" property to control distance between ticks when tickmode is auto #303

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

Closed
wants to merge 15 commits into from

Conversation

john-soklaski
Copy link
Contributor

I have a resizeable chart that I want Plotly to automatically manage the ticks for. But, the ticks are positioned too closely together. To address this, I added a tickpadding property to the axis object.

Before

image

After (with tickpadding:20)

image

http://codepen.io/john-soklaski/pen/LNEqWW

@etpinard
Copy link
Contributor

etpinard commented Mar 4, 2016

Thanks for the PR.

I think this could be a valuable addition. As you mentioned, nticks does not play well with graphs of varying sizes.

That said, we must make sure that the nticks and tickpadding don't interfere. We want nticks to retain its meaning. One solution would be to disallow tickpadding when nticks is set.

In other words, we don't want to give users multiple ways of describing the same graph.

@john-soklaski
Copy link
Contributor Author

Thanks for the feedback.

In the current implementation, tickpadding is only applied if nticks is not set. But, that's an implementation detail and it would be better to enforce upfront. I've changed it to ignore the value of tickpadding if nticks is set. Is there a mechanism to warn the users if this happens?

Also, I'd like to add a chart with tickpadding as part of the image diffing suite. Do I just need to add a .json file to image/mocks?

@jackparmer
Copy link
Contributor

Hey @john-soklaski - Would you mind reaching us through this form so we can contact you by email?
https://plot.ly/products/enterprise/get-in-touch/
Thanks!

@john-soklaski
Copy link
Contributor Author

@jackparmer Yep! I submitted through the form.

@john-soklaski
Copy link
Contributor Author

Updated with added image test for tickpadding.

@etpinard
Copy link
Contributor

etpinard commented Mar 9, 2016

@john-soklaski After a more thorough review, I noticed a few things left to address, most importantly,
regarding the added and currently not-tested colorbar and gl3d pathways.

Axis attribute logic is reused by the colorbar component and gl3d axes. To make the the tick_defaults supplier work for all cases you added tickpadding to the colorbar attributes and the gl3d attributes. This inadvertently exposes your tickpadding attribute to all plots with colorbar and all gl3d plots.

So, going forward:

  • tickpadding for colorbars would a nice (and free) addition given that you add a test image for it.
  • while gl3d axes uses the same defaults logic as cartesian axes, the axis ticks are computed separately in plots/gl3d/layout/tick_marks.js. Either you'll incorporate tickpadding in the above method (which may be more trouble than it's worth) or find a way to remove the tickpadding from the gl3d axis attributes.

Moreover,

  • the tickpadding vs nticks logics that added here would be suited for tick_value_defaults.js where it could use the coerced nticks and tickmode values instead of digging into containerOut (which we consider an slight anti-pattern).

@john-soklaski
Copy link
Contributor Author

@etpinard

while gl3d axes uses the same defaults logic as cartesian axes, the axis ticks are computed separately in plots/gl3d/layout/tick_marks.js. Either you'll incorporate tickpadding in the above method (which may be more trouble than it's worth) or find a way to remove the tickpadding from the gl3d axis attributes.

The most straightforward way I found was to continue to define tickpadding in gl3d's axis_attributes, but to delete the property immediately following the general coercion of handleAxisDefaults.

|
|

the tickpadding vs nticks logics that added here would be suited for tick_value_defaults.js where it could use the coerced nticks and tickmode values instead of digging into containerOut (which we consider an slight anti-pattern).

Thanks, this feels much cleaner.

|
|

tickpadding for colorbars would a nice (and free) addition given that you add a test image for it.

As I was adding a colorbar test, I realized that tickpadding wasn't behaving in an intuitive way for a noncategorical axis.

For a categorical axis, it works great because dtick varies linearly with roughDTick:

ax.dtick = Math.ceil(Math.max(roughDTick, 1));

But for a linear axis, the behavior is unintuitive, as dtick gets rounded to base 10 multiples of 2, 5, and 10:

roundBase10 = [2, 5, 10]

...

base = Math.pow(10, Math.floor(Math.log(roughDTick) / Math.LN10));
ax.dtick = roundDTick(roughDTick, base, roundBase10);

tickpadding functions by influencing how ax.nticks is automatically calculated, so naturally ax.nticks exhibits this behavior as well.

What do you think about limiting this to just categorical axes? Or, alternatively, what do you think of applying tickpadding to the calculated ax.dtick value (only for numeric dticks)?

@etpinard
Copy link
Contributor

@john-soklaski I apologize for the wait. I've been on a tight schedule this week.

The most straightforward way I found was to continue to define tickpadding in gl3d's axis_attributes, but to delete the property immediately following the general coercion of handleAxisDefaults

I'd vote 👎 on this. Adding ghost attributes to the gl3d axes attributes would lead to misleading schema references.

Instead, you could add tickpadding to an extended (you can use Lib.extend({}, )) at some point before this line. The goal is to have Plotly.PlotSchema.get() not include tickpadding under layout.scene.[xyz]axis, while passing the required attribute object to handleAxisDefaults. Note that Plotly.PlotSchema.get() is what we use internally to build our reference pages.

You're correct about the colorbar ticks behaving a little bit differently in this case. I don't think tickpadding
adds much value to colorbars. Colorbars aren't dynamically rescaled very often; nticks is good enough. So, I don't see the need to refactor the colorbar code to add support for tickpadding.

Therefore, maybe you could try to implement to same sort of trickery mentioned ⏫ in the colorbar code as for gl3d axes ?

@john-soklaski
Copy link
Contributor Author

@etpinard Thanks for your feedback!

Instead, you could add tickpadding to an extended (you can use Lib.extend({}, )) at some point before this line. The goal is to have Plotly.PlotSchema.get() not include tickpadding under layout.scene.[xyz]axis, while passing the required attribute object to handleAxisDefaults. Note that Plotly.PlotSchema.get() is what we use internally to build our reference pages.

Gotcha, that makes sense, I'll implement it that way.

Colorbars aren't dynamically rescaled very often; nticks is good enough. So, I don't see the need to refactor the colorbar code to add support for tickpadding.

I need to take another look at this, but as far as I know, the unintuitive behavior occurs for any axis with tickmode: auto that aren't of type: category. It affects the calculated nticks, but only causes changes at certain thresholds, due to the rounding. If it's possible to make this behavior make more sense for non-categorical axes, I think the colorbar support should be free (as you initially predicted).

Although, I'd like for tickpadding to be generally applicable to any axis type, if it isn't feasible to do so, it is certainly useful for categorical axes as is.

I'll have more time to take a look at this in about a week.

@john-soklaski
Copy link
Contributor Author

@etpinard

Therefore, maybe you could try to implement to same sort of trickery mentioned ⏫ in the colorbar code as for gl3d axes ?

Sorry it took me so long to get back to this. I updated with the changes mentioned for both gl3d and colorbar. Is this along the lines that you were thinking?

@@ -25,8 +26,11 @@ var gridLightness = 100 * (204 - 0x44) / (255 - 0x44);
module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, options) {
var containerIn, containerOut;

//gl3d doesn't currently implement tickpadding property, but it is a required attribute of a cartesian axis
var cartesianLayoutAttributes = Lib.extendFlat({}, layoutAttributes, { tickpadding: cartesianAxesAttrs.tickpadding });
Copy link
Contributor

Choose a reason for hiding this comment

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

yep, exactly. Nicely done.

@talgalili
Copy link

Following on what @alexcjohnson wrote on #1812 - please add the #1812 feature into this pull request (once it resolves the conflicts).

Thanks!

@talgalili
Copy link

@john-soklaski any chance you would be able to give this a look?

@talgalili
Copy link

Bump.
@john-soklaski any chance you would be able to give this a look?
(sorry for nagging, but this would really benefit a project I'm involved in - the heatmaply R package)

@jackparmer
Copy link
Contributor

Hi @talgalili - Does your research group have a budget to sponsor or purchase software? I can't speak for John, but the plotly.js team is flat out right now with other projects. I don't expect to see this merged this month without a sponsor. Seems like your research group is doing some really nice work with plotly.js, so thought I'd share a realistic idea of timeline and priority.

@talgalili
Copy link

Hi @jackparmer
All participants in the heatmaply project are from different countries and are contributing their efforts and time freely for this as an open source project (although I did get partial funding for some of the time I spent on the package).
Hence, I sadly don't see any source of funding at this point, and cannot offer it to expedite matters.
I shall patiently wait in the hopes this would some day be merged.

With regards,
Tal

@etpinard
Copy link
Contributor

etpinard commented Apr 3, 2019

Closing this thing (unfortunately).

Those merge conflicts are probably too hard to try to solve on this branch.

If anyone subscribed to this is still interested in this feature, please open a new issue.

@etpinard etpinard closed this Apr 3, 2019
@etpinard
Copy link
Contributor

etpinard commented May 1, 2019

... actually #1965 is probably the best place to discuss "tickpadding"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature something new
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants