Skip to content

fix for spikedistance set to infinity #4627

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 2 commits into from

Conversation

antoinerg
Copy link
Contributor

@antoinerg antoinerg commented Mar 11, 2020

@@ -549,7 +549,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
var thisSpikeDistance;
for(var i = 0; i < pointsData.length; i++) {
thisSpikeDistance = pointsData[i].spikeDistance;
if(thisSpikeDistance < minDistance && thisSpikeDistance <= spikedistance) {
if(thisSpikeDistance <= minDistance && thisSpikeDistance <= spikedistance) {
Copy link
Contributor Author

@antoinerg antoinerg Mar 11, 2020

Choose a reason for hiding this comment

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

The problem stems from thisSpikeDistance being Infinity and minDistance also being Infinity. Without an equal sign, this will never be true and no spikelines will appear hence the bug.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Are there any cases this changes which point we get spikes to? It might still be OK in that case, I just want to know what those cases are. The loop indicates this way if we have multiple items in pointData all with the same spikeDistance, previously we'd get the first one, but with the new logic we'll get the last one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are there any cases this changes which point we get spikes to?

@alexcjohnson I'm not sure how to proceed to find out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should we check whether minDistance is Infinity and handle that case separately?

Copy link
Contributor

Choose a reason for hiding this comment

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

That's a much better solution, IMO.

Copy link
Contributor

Choose a reason for hiding this comment

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

if((minDistance === Infinity || thisSpikeDistance < minDistance) &&
    thisSpikeDistance <= spikedistance
) {

looks like the right logic to apply.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok so I went with this safer approach. If spikedistance is Infinity we visit that if block. It should preserve any existing behavior but fix the edge case for Infinity.

See 583ad64

Copy link
Collaborator

Choose a reason for hiding this comment

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

The key is to first identify the relevant test cases. I suspect the relevant ones are (with hovermode: 'x'):

  • Two scatter traces with exactly identical points, so there aren't closer and farther ones. Maybe we don't care which one gets the spike line... though offhand I'd suggest the last one, since it'll be drawn on top so you'll see a spike line color matching the visible point.
  • Stacked bar traces with the cursor at a larger (or smaller) y value than any of the bars. Ideally I'd think it would be nice to draw the spike line to the one that's closest; but that would require getting away from using Infinity for all points outside the bar, at least for sizeFn. Perhaps we give Fx.inbox another (optional) argument failVal that, in this case, will be set very large, and increasing the farther away you get from the bar either above or below, but not infinite. Or, at that point it seems silly to use Fx.inbox at all, just inline this logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the clarification @alexcjohnson . I now better understand the purpose of this code. I will take another approach.

@archmoj archmoj added status: reviewable bug something broken labels Mar 11, 2020
@archmoj
Copy link
Contributor

archmoj commented Mar 11, 2020

@antoinerg Thanks very much for the PR.
Looks good to my eyes.
I'll let a second reviewer to give you dancers.

@archmoj archmoj requested a review from alexcjohnson March 11, 2020 18:22
@antoinerg antoinerg mentioned this pull request Mar 11, 2020
4 tasks
@archmoj
Copy link
Contributor

archmoj commented Mar 11, 2020

Nicely done.
💃

@archmoj
Copy link
Contributor

archmoj commented Mar 11, 2020

Please hold on. There is a new comment: #4627 (comment).

@antoinerg antoinerg force-pushed the fix-spikeline-infinity branch 2 times, most recently from 7e787ad to 9a0143f Compare March 12, 2020 00:57
@antoinerg antoinerg force-pushed the fix-spikeline-infinity branch from 9a0143f to ebf75e6 Compare March 12, 2020 01:04
@antoinerg
Copy link
Contributor Author

antoinerg commented Mar 12, 2020

I made a mess earlier and cleaned up the git history with a git rebase. I left commit ae7db42 with the failing test to fix and made a new solution in ebf75e6 .

P.S. I updated the Codepen above to run the latest build.

@antoinerg antoinerg added this to the v1.53.0 milestone Mar 12, 2020
@antoinerg antoinerg self-assigned this Mar 12, 2020
@antoinerg
Copy link
Contributor Author

I think my first solution has to go back in otherwise we have too many non-scatter traces for which no spike lines appear for spikedistance: -1.

@alexcjohnson can you have a look at branch fix-spikedistance. It contains new tests which make sure that:

  • all cartesian traces produce spike lines when spikedistance: -1 (first commit)
  • test that spikeline is drawn up to the last point as you described
  • test that spikeline is drawn up to the closest bar

If it's satisfactory, I can open a new PR or simply force push here. Let me know what you prefer.

@antoinerg
Copy link
Contributor Author

@archmoj you might also want to review my new branch described in #4627 (comment)

@alexcjohnson
Copy link
Collaborator

@alexcjohnson can you have a look at branch fix-spikedistance. It contains new tests...

Looks great, my only question about it is the test "correctly select the closest bar even when setting spikedistance to -1" - you do _hover({xpx: 600, ypx: 400}); and _hover({xpx: 580, ypx: 200});, which look like they're within the bounds of the blue and green bars at E? That's important (though it would be clearer with exactly the same xpx), but I would have expected to also see ypx corresponding to positions not on any bars, but above and below the entire stack - which would probably require increasing the range to create space above and below. I'm not sure if that works right now but I think the goal of #3805 would be that if you get a hover point from a bar, and you set spikedistance=-1, you should get a spike line to the closest one.

@archmoj
Copy link
Contributor

archmoj commented Mar 13, 2020

If it's satisfactory, I can open a new PR or simply force push here. Let me know what you prefer.

Force-pushing on PRs is discouraged on the plotly.js repo.
Please simply add the commit to this PR or open a new PR.
Thank you!

@antoinerg
Copy link
Contributor Author

my only question about it is the test "correctly select the closest bar even when setting spikedistance to -1" - you do _hover({xpx: 600, ypx: 400}); and _hover({xpx: 580, ypx: 200});, which look like they're within the bounds of the blue and green bars at E?

I'm not completely sure: maybe it's above or below. I tested it manually on mock bar_stack-with-gaps to make sure we get the closest one.

That's important (though it would be clearer with exactly the same xpx)

Yes they should have the same xpx, sorry for making things confusing. I will fix that.

but I would have expected to also see ypx corresponding to positions not on any bars, but above and below the entire stack - which would probably require increasing the range to create space above and below. I'm not sure if that works right now

Right now, for bar traces, spike lines will appear only if you hover inside the bar itself for any value spikedistance > 0 (this is also the case on master). My PR fix-spikedistance only fixes the case spikedistance = -1 which is key for unified hover label. I'm not sure if I have time to tackle the other case (ie spikedistance > 0 ) at the moment.

if you get a hover point from a bar, and you set spikedistance=-1, you should get a spike line to the closest one.

I think this case is covered: https://codepen.io/antoinerg/pen/vYORyLV

cc @alexcjohnson

@alexcjohnson
Copy link
Collaborator

You're so close! Right now you get a spike to the last bar when you're off the stack, not the closest one (in the gif below see behavior when the mouse is below, spike goes to the green bar). fixing that would require tweaking sizefn to include some large-but-not-infinite value when off the bar, that grows larger as you get farther away.
Kapture 2020-03-13 at 8 46 42

This is not a super important case, so if you want to move on that's fine, but if you do please make a new issue for this.

@antoinerg
Copy link
Contributor Author

antoinerg commented Mar 13, 2020

You're so close! Right now you get a spike to the last bar when you're off the stack, not the closest one (in the gif below see behavior when the mouse is below, spike goes to the green bar). fixing that would require tweaking sizefn to include some large-but-not-infinite value when off the bar, that grows larger as you get farther away.
Kapture 2020-03-13 at 8 46 42

This is not a super important case, so if you want to move on that's fine, but if you do please make a new issue for this.

I missed that behavior! Let me see if I can get it right :) Thanks for the review @alexcjohnson 🕵️‍♂️

EDIT: I am not sure I can at the moment. I don't understand the current calculation of spikedistance and what it is supposed to represent. The equations make no sense to me. I'll open an issue and revisit later if time permits.

@antoinerg
Copy link
Contributor Author

Please simply add the commit to this PR or open a new PR.

I'll open a new PR. Closing in favor of #4637

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.

3 participants