Skip to content

Fix rangebreaks overlapping and tick positions - #4831

Merged
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks
Jun 3, 2020
Merged

Fix rangebreaks overlapping and tick positions#4831
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks

Conversation

@archmoj

@archmojarchmoj commented May 13, 2020

Copy link
Copy Markdown
Contributor

Supersedes #4734 and fixes#4722 namely the first & second parts of #4722 (comment) i.e. when dtick is set as well as auto ticks.

demo: Before vs After

This PR also fixes#4879 by 5c8055b commit.

@plotly/plotly_js

@archmojarchmoj added this to the v1.54.2 milestone May 13, 2020
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Comment threadsrc/plots/cartesian/axes.js Outdated
var tick0 = r2l(ax.tick0);

if(ax.tickmode === 'auto' && ax.rangebreaks && ax.maskBreaks(tick0) === BADNUM) {
tick0 = moveToEndOfBreak(tick0, ax);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This still bothers me - I see it's only in auto mode but it seems like this will still have strange effects, especially if you do something unusual with the bounds of the break, like [8.75, 17.25]. That said I don't understand how we're getting the results we are in axes_breaks-dtick_auto of ticks at 9am and noon, ie alternating 3-hour and 5-hour gaps. If we're hitting this block then tick0 gets set to 9am, but then to get a tick at noon we'd need a 3-hour dtick, which would then put another tick at 3pm - not what we see. And I don't think we want a 3/5 alternation as an autotick result anyway, we should regularize that to consistent 4-hour spacing.

So a couple of image tests, like you have, are good. But I think we also want to see a bunch of jasmine tests where we just set up an axis and list the ticks (positions and labels) that result within one day. That should let us cover a whole lot more cases: auto-determined dtick from 1 hour to a day and everything between, and a few manually set dtick and tick0 values; each of these tested against each of the hourly rangebreaks I mentioned in #4722 (comment)

@archmoj

archmoj commented May 15, 2020

Copy link
Copy Markdown
ContributorAuthor

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Good call. Fixed in 4eab137 & a7633c3.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

Update:
Just pushed my attempt on improving ticks in the mode auto into this PR.

Comment threadsrc/plots/cartesian/axis_defaults.js Outdated
}

// break when found all types
if(n === 2) break;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what if the user includes two breaks of one type, THEN a break of the other type? I suppose I can theoretically imagine wanting two disjoint hour periods - a morning shift and an evening shift, with a midday break? I wouldn't worry about doing something "pretty" in this case, perhaps just set _dayHours to something like 1 or 2 so we go straight from day to hour ticks or perhaps just use the first break. But it definitely shouldn't stop us from noticing _hasDayOfWeekBreaks

And vice versa I guess... maybe someone wants to skip Sundays and Wednesdays? Again, weird, but shouldn't stop us from catching _hasHourBreaks

Comment threadsrc/plots/cartesian/axes.js Outdated
case 18: return [1, 2, 3, 6, 9];
case 20: return [1, 2, 4, 5, 10];
case 21: return [1, 3, 7];
case 22: return [1, 2, 11];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oh interesting... so just a precise list of factors of the rounded number of visible hours. I'm not sure we really want all of these, and we might want to add something intermediate for the larger primes so we don't jump straight from 1 day to 1 hour, even though we can't do it precisely uniformly. But this is a great starting point anyway, we can tweak later.

However, looking at the mocks changed in this PR it seems like there's a problem when dtick is not an even fraction of a day. For example in axes_breaks-candlestick2, dtick is 18 hours (how did that happen? I only see 9 here, I would have thought it would go to 24 after that? That doesn't matter though, there are lots of periods we want that don't divide 24 evenly, this is just an example), and as a result some days have 2 ticks (at 9:30 and 12:00) and other days have only one (at 9:30).

Trying to figure out a reasonable way to handle this, in conjunction with tick0 possibly being set manually. I think what we may need to say is: when you have hourly rangebreaks and dtick < 24h, the only piece of tick0 that we consider is the time portion and we start at that time on each new day, then increment by dtick until we get to the next day, at which point we reset the time to tick0 again, so you get ticks at the same hours in every day.

@archmojarchmoj changed the title Fix ticks with defined dtick on axes with rangebreaksImprove ticks on axes with rangebreaksJun 2, 2020
@archmoj
archmojforce-pushed the rangebreaks-improve-ticks branch from 9b45339 to c5cf45aCompareJune 3, 2020 02:01
@archmoj

Copy link
Copy Markdown
ContributorAuthor

This PR is now ready for final review.

if(ax.tickmode === 'array') nt *= 100;


ax._roughDTick = (Math.abs(rng[1] - rng[0]) - (ax._lBreaks || 0)) / nt;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking much nicer now!

I'm just noticing that the auto dtick we get depends on whether there's a break within the visible range or not, which seems weird, and seems like exactly what this - ax._lBreaks was designed to avoid. For example (back on everyone's favorite, axes_breaks-candlestick2 😅) if I zoom in while keeping a break in range I can't get dtick less than 2 hours:
Screen Shot 2020-06-02 at 10 55 55 PM

But shift the break off the edge with exactly the same scale and it snaps to 15 min:
Screen Shot 2020-06-02 at 10 57 52 PM

Is there something bad that happens if this line is left as it was?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good catch. Addressed in 9241578.

- adjust tick spacing on x axes
- fixup tests

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Beautiful! Thanks for being persistent with this issue. This is a huge improvement - there still may be some cases we want to adjust, but that's pretty minor now, most cases look really good and the pan/zoom behavior (at least with rangesliders) is quite nice. 🎉 💃

@archmojarchmoj changed the title Improve ticks on axes with rangebreaksFix rangebreaks overlapping and tick positionsJun 3, 2020
@archmoj
archmoj merged commit f90690f into masterJun 3, 2020
@archmoj
archmoj deleted the rangebreaks-improve-ticks branch June 3, 2020 17:32
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugsomething broken

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Problem overlapping rangebreaks Tick labels when using hourly rangebreaks

2 participants

@archmoj@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Fix rangebreaks overlapping and tick positions by archmoj · Pull Request #4831 · plotly/plotly.js · GitHub
Skip to content

Fix rangebreaks overlapping and tick positions - #4831

Merged
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks
Jun 3, 2020
Merged

Fix rangebreaks overlapping and tick positions#4831
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks

Conversation

@archmoj

@archmojarchmoj commented May 13, 2020

Copy link
Copy Markdown
Contributor

Supersedes #4734 and fixes#4722 namely the first & second parts of #4722 (comment) i.e. when dtick is set as well as auto ticks.

demo: Before vs After

This PR also fixes#4879 by 5c8055b commit.

@plotly/plotly_js

@archmojarchmoj added this to the v1.54.2 milestone May 13, 2020
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Comment threadsrc/plots/cartesian/axes.js Outdated
var tick0 = r2l(ax.tick0);

if(ax.tickmode === 'auto' && ax.rangebreaks && ax.maskBreaks(tick0) === BADNUM) {
tick0 = moveToEndOfBreak(tick0, ax);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This still bothers me - I see it's only in auto mode but it seems like this will still have strange effects, especially if you do something unusual with the bounds of the break, like [8.75, 17.25]. That said I don't understand how we're getting the results we are in axes_breaks-dtick_auto of ticks at 9am and noon, ie alternating 3-hour and 5-hour gaps. If we're hitting this block then tick0 gets set to 9am, but then to get a tick at noon we'd need a 3-hour dtick, which would then put another tick at 3pm - not what we see. And I don't think we want a 3/5 alternation as an autotick result anyway, we should regularize that to consistent 4-hour spacing.

So a couple of image tests, like you have, are good. But I think we also want to see a bunch of jasmine tests where we just set up an axis and list the ticks (positions and labels) that result within one day. That should let us cover a whole lot more cases: auto-determined dtick from 1 hour to a day and everything between, and a few manually set dtick and tick0 values; each of these tested against each of the hourly rangebreaks I mentioned in #4722 (comment)

@archmoj

archmoj commented May 15, 2020

Copy link
Copy Markdown
ContributorAuthor

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Good call. Fixed in 4eab137 & a7633c3.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

Update:
Just pushed my attempt on improving ticks in the mode auto into this PR.

Comment threadsrc/plots/cartesian/axis_defaults.js Outdated
}

// break when found all types
if(n === 2) break;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what if the user includes two breaks of one type, THEN a break of the other type? I suppose I can theoretically imagine wanting two disjoint hour periods - a morning shift and an evening shift, with a midday break? I wouldn't worry about doing something "pretty" in this case, perhaps just set _dayHours to something like 1 or 2 so we go straight from day to hour ticks or perhaps just use the first break. But it definitely shouldn't stop us from noticing _hasDayOfWeekBreaks

And vice versa I guess... maybe someone wants to skip Sundays and Wednesdays? Again, weird, but shouldn't stop us from catching _hasHourBreaks

Comment threadsrc/plots/cartesian/axes.js Outdated
case 18: return [1, 2, 3, 6, 9];
case 20: return [1, 2, 4, 5, 10];
case 21: return [1, 3, 7];
case 22: return [1, 2, 11];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oh interesting... so just a precise list of factors of the rounded number of visible hours. I'm not sure we really want all of these, and we might want to add something intermediate for the larger primes so we don't jump straight from 1 day to 1 hour, even though we can't do it precisely uniformly. But this is a great starting point anyway, we can tweak later.

However, looking at the mocks changed in this PR it seems like there's a problem when dtick is not an even fraction of a day. For example in axes_breaks-candlestick2, dtick is 18 hours (how did that happen? I only see 9 here, I would have thought it would go to 24 after that? That doesn't matter though, there are lots of periods we want that don't divide 24 evenly, this is just an example), and as a result some days have 2 ticks (at 9:30 and 12:00) and other days have only one (at 9:30).

Trying to figure out a reasonable way to handle this, in conjunction with tick0 possibly being set manually. I think what we may need to say is: when you have hourly rangebreaks and dtick < 24h, the only piece of tick0 that we consider is the time portion and we start at that time on each new day, then increment by dtick until we get to the next day, at which point we reset the time to tick0 again, so you get ticks at the same hours in every day.

@archmojarchmoj changed the title Fix ticks with defined dtick on axes with rangebreaksImprove ticks on axes with rangebreaksJun 2, 2020
@archmoj
archmojforce-pushed the rangebreaks-improve-ticks branch from 9b45339 to c5cf45aCompareJune 3, 2020 02:01
@archmoj

Copy link
Copy Markdown
ContributorAuthor

This PR is now ready for final review.

if(ax.tickmode === 'array') nt *= 100;


ax._roughDTick = (Math.abs(rng[1] - rng[0]) - (ax._lBreaks || 0)) / nt;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking much nicer now!

I'm just noticing that the auto dtick we get depends on whether there's a break within the visible range or not, which seems weird, and seems like exactly what this - ax._lBreaks was designed to avoid. For example (back on everyone's favorite, axes_breaks-candlestick2 😅) if I zoom in while keeping a break in range I can't get dtick less than 2 hours:
Screen Shot 2020-06-02 at 10 55 55 PM

But shift the break off the edge with exactly the same scale and it snaps to 15 min:
Screen Shot 2020-06-02 at 10 57 52 PM

Is there something bad that happens if this line is left as it was?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good catch. Addressed in 9241578.

- adjust tick spacing on x axes
- fixup tests

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Beautiful! Thanks for being persistent with this issue. This is a huge improvement - there still may be some cases we want to adjust, but that's pretty minor now, most cases look really good and the pan/zoom behavior (at least with rangesliders) is quite nice. 🎉 💃

@archmojarchmoj changed the title Improve ticks on axes with rangebreaksFix rangebreaks overlapping and tick positionsJun 3, 2020
@archmoj
archmoj merged commit f90690f into masterJun 3, 2020
@archmoj
archmoj deleted the rangebreaks-improve-ticks branch June 3, 2020 17:32
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugsomething broken

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Problem overlapping rangebreaks Tick labels when using hourly rangebreaks

2 participants

@archmoj@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fix rangebreaks overlapping and tick positions by archmoj · Pull Request #4831 · plotly/plotly.js · GitHub
Skip to content

Fix rangebreaks overlapping and tick positions - #4831

Merged
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks
Jun 3, 2020
Merged

Fix rangebreaks overlapping and tick positions#4831
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks

Conversation

@archmoj

@archmojarchmoj commented May 13, 2020

Copy link
Copy Markdown
Contributor

Supersedes #4734 and fixes#4722 namely the first & second parts of #4722 (comment) i.e. when dtick is set as well as auto ticks.

demo: Before vs After

This PR also fixes#4879 by 5c8055b commit.

@plotly/plotly_js

@archmojarchmoj added this to the v1.54.2 milestone May 13, 2020
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Comment threadsrc/plots/cartesian/axes.js Outdated
var tick0 = r2l(ax.tick0);

if(ax.tickmode === 'auto' && ax.rangebreaks && ax.maskBreaks(tick0) === BADNUM) {
tick0 = moveToEndOfBreak(tick0, ax);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This still bothers me - I see it's only in auto mode but it seems like this will still have strange effects, especially if you do something unusual with the bounds of the break, like [8.75, 17.25]. That said I don't understand how we're getting the results we are in axes_breaks-dtick_auto of ticks at 9am and noon, ie alternating 3-hour and 5-hour gaps. If we're hitting this block then tick0 gets set to 9am, but then to get a tick at noon we'd need a 3-hour dtick, which would then put another tick at 3pm - not what we see. And I don't think we want a 3/5 alternation as an autotick result anyway, we should regularize that to consistent 4-hour spacing.

So a couple of image tests, like you have, are good. But I think we also want to see a bunch of jasmine tests where we just set up an axis and list the ticks (positions and labels) that result within one day. That should let us cover a whole lot more cases: auto-determined dtick from 1 hour to a day and everything between, and a few manually set dtick and tick0 values; each of these tested against each of the hourly rangebreaks I mentioned in #4722 (comment)

@archmoj

archmoj commented May 15, 2020

Copy link
Copy Markdown
ContributorAuthor

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Good call. Fixed in 4eab137 & a7633c3.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

Update:
Just pushed my attempt on improving ticks in the mode auto into this PR.

Comment threadsrc/plots/cartesian/axis_defaults.js Outdated
}

// break when found all types
if(n === 2) break;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what if the user includes two breaks of one type, THEN a break of the other type? I suppose I can theoretically imagine wanting two disjoint hour periods - a morning shift and an evening shift, with a midday break? I wouldn't worry about doing something "pretty" in this case, perhaps just set _dayHours to something like 1 or 2 so we go straight from day to hour ticks or perhaps just use the first break. But it definitely shouldn't stop us from noticing _hasDayOfWeekBreaks

And vice versa I guess... maybe someone wants to skip Sundays and Wednesdays? Again, weird, but shouldn't stop us from catching _hasHourBreaks

Comment threadsrc/plots/cartesian/axes.js Outdated
case 18: return [1, 2, 3, 6, 9];
case 20: return [1, 2, 4, 5, 10];
case 21: return [1, 3, 7];
case 22: return [1, 2, 11];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oh interesting... so just a precise list of factors of the rounded number of visible hours. I'm not sure we really want all of these, and we might want to add something intermediate for the larger primes so we don't jump straight from 1 day to 1 hour, even though we can't do it precisely uniformly. But this is a great starting point anyway, we can tweak later.

However, looking at the mocks changed in this PR it seems like there's a problem when dtick is not an even fraction of a day. For example in axes_breaks-candlestick2, dtick is 18 hours (how did that happen? I only see 9 here, I would have thought it would go to 24 after that? That doesn't matter though, there are lots of periods we want that don't divide 24 evenly, this is just an example), and as a result some days have 2 ticks (at 9:30 and 12:00) and other days have only one (at 9:30).

Trying to figure out a reasonable way to handle this, in conjunction with tick0 possibly being set manually. I think what we may need to say is: when you have hourly rangebreaks and dtick < 24h, the only piece of tick0 that we consider is the time portion and we start at that time on each new day, then increment by dtick until we get to the next day, at which point we reset the time to tick0 again, so you get ticks at the same hours in every day.

@archmojarchmoj changed the title Fix ticks with defined dtick on axes with rangebreaksImprove ticks on axes with rangebreaksJun 2, 2020
@archmoj
archmojforce-pushed the rangebreaks-improve-ticks branch from 9b45339 to c5cf45aCompareJune 3, 2020 02:01
@archmoj

Copy link
Copy Markdown
ContributorAuthor

This PR is now ready for final review.

if(ax.tickmode === 'array') nt *= 100;


ax._roughDTick = (Math.abs(rng[1] - rng[0]) - (ax._lBreaks || 0)) / nt;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking much nicer now!

I'm just noticing that the auto dtick we get depends on whether there's a break within the visible range or not, which seems weird, and seems like exactly what this - ax._lBreaks was designed to avoid. For example (back on everyone's favorite, axes_breaks-candlestick2 😅) if I zoom in while keeping a break in range I can't get dtick less than 2 hours:
Screen Shot 2020-06-02 at 10 55 55 PM

But shift the break off the edge with exactly the same scale and it snaps to 15 min:
Screen Shot 2020-06-02 at 10 57 52 PM

Is there something bad that happens if this line is left as it was?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good catch. Addressed in 9241578.

- adjust tick spacing on x axes
- fixup tests

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Beautiful! Thanks for being persistent with this issue. This is a huge improvement - there still may be some cases we want to adjust, but that's pretty minor now, most cases look really good and the pan/zoom behavior (at least with rangesliders) is quite nice. 🎉 💃

@archmojarchmoj changed the title Improve ticks on axes with rangebreaksFix rangebreaks overlapping and tick positionsJun 3, 2020
@archmoj
archmoj merged commit f90690f into masterJun 3, 2020
@archmoj
archmoj deleted the rangebreaks-improve-ticks branch June 3, 2020 17:32
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugsomething broken

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Problem overlapping rangebreaks Tick labels when using hourly rangebreaks

2 participants

@archmoj@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fix rangebreaks overlapping and tick positions by archmoj · Pull Request #4831 · plotly/plotly.js · GitHub
Skip to content

Fix rangebreaks overlapping and tick positions - #4831

Merged
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks
Jun 3, 2020
Merged

Fix rangebreaks overlapping and tick positions#4831
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks

Conversation

@archmoj

@archmojarchmoj commented May 13, 2020

Copy link
Copy Markdown
Contributor

Supersedes #4734 and fixes#4722 namely the first & second parts of #4722 (comment) i.e. when dtick is set as well as auto ticks.

demo: Before vs After

This PR also fixes#4879 by 5c8055b commit.

@plotly/plotly_js

@archmojarchmoj added this to the v1.54.2 milestone May 13, 2020
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Comment threadsrc/plots/cartesian/axes.js Outdated
var tick0 = r2l(ax.tick0);

if(ax.tickmode === 'auto' && ax.rangebreaks && ax.maskBreaks(tick0) === BADNUM) {
tick0 = moveToEndOfBreak(tick0, ax);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This still bothers me - I see it's only in auto mode but it seems like this will still have strange effects, especially if you do something unusual with the bounds of the break, like [8.75, 17.25]. That said I don't understand how we're getting the results we are in axes_breaks-dtick_auto of ticks at 9am and noon, ie alternating 3-hour and 5-hour gaps. If we're hitting this block then tick0 gets set to 9am, but then to get a tick at noon we'd need a 3-hour dtick, which would then put another tick at 3pm - not what we see. And I don't think we want a 3/5 alternation as an autotick result anyway, we should regularize that to consistent 4-hour spacing.

So a couple of image tests, like you have, are good. But I think we also want to see a bunch of jasmine tests where we just set up an axis and list the ticks (positions and labels) that result within one day. That should let us cover a whole lot more cases: auto-determined dtick from 1 hour to a day and everything between, and a few manually set dtick and tick0 values; each of these tested against each of the hourly rangebreaks I mentioned in #4722 (comment)

@archmoj

archmoj commented May 15, 2020

Copy link
Copy Markdown
ContributorAuthor

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Good call. Fixed in 4eab137 & a7633c3.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

Update:
Just pushed my attempt on improving ticks in the mode auto into this PR.

Comment threadsrc/plots/cartesian/axis_defaults.js Outdated
}

// break when found all types
if(n === 2) break;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what if the user includes two breaks of one type, THEN a break of the other type? I suppose I can theoretically imagine wanting two disjoint hour periods - a morning shift and an evening shift, with a midday break? I wouldn't worry about doing something "pretty" in this case, perhaps just set _dayHours to something like 1 or 2 so we go straight from day to hour ticks or perhaps just use the first break. But it definitely shouldn't stop us from noticing _hasDayOfWeekBreaks

And vice versa I guess... maybe someone wants to skip Sundays and Wednesdays? Again, weird, but shouldn't stop us from catching _hasHourBreaks

Comment threadsrc/plots/cartesian/axes.js Outdated
case 18: return [1, 2, 3, 6, 9];
case 20: return [1, 2, 4, 5, 10];
case 21: return [1, 3, 7];
case 22: return [1, 2, 11];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oh interesting... so just a precise list of factors of the rounded number of visible hours. I'm not sure we really want all of these, and we might want to add something intermediate for the larger primes so we don't jump straight from 1 day to 1 hour, even though we can't do it precisely uniformly. But this is a great starting point anyway, we can tweak later.

However, looking at the mocks changed in this PR it seems like there's a problem when dtick is not an even fraction of a day. For example in axes_breaks-candlestick2, dtick is 18 hours (how did that happen? I only see 9 here, I would have thought it would go to 24 after that? That doesn't matter though, there are lots of periods we want that don't divide 24 evenly, this is just an example), and as a result some days have 2 ticks (at 9:30 and 12:00) and other days have only one (at 9:30).

Trying to figure out a reasonable way to handle this, in conjunction with tick0 possibly being set manually. I think what we may need to say is: when you have hourly rangebreaks and dtick < 24h, the only piece of tick0 that we consider is the time portion and we start at that time on each new day, then increment by dtick until we get to the next day, at which point we reset the time to tick0 again, so you get ticks at the same hours in every day.

@archmojarchmoj changed the title Fix ticks with defined dtick on axes with rangebreaksImprove ticks on axes with rangebreaksJun 2, 2020
@archmoj
archmojforce-pushed the rangebreaks-improve-ticks branch from 9b45339 to c5cf45aCompareJune 3, 2020 02:01
@archmoj

Copy link
Copy Markdown
ContributorAuthor

This PR is now ready for final review.

if(ax.tickmode === 'array') nt *= 100;


ax._roughDTick = (Math.abs(rng[1] - rng[0]) - (ax._lBreaks || 0)) / nt;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking much nicer now!

I'm just noticing that the auto dtick we get depends on whether there's a break within the visible range or not, which seems weird, and seems like exactly what this - ax._lBreaks was designed to avoid. For example (back on everyone's favorite, axes_breaks-candlestick2 😅) if I zoom in while keeping a break in range I can't get dtick less than 2 hours:
Screen Shot 2020-06-02 at 10 55 55 PM

But shift the break off the edge with exactly the same scale and it snaps to 15 min:
Screen Shot 2020-06-02 at 10 57 52 PM

Is there something bad that happens if this line is left as it was?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good catch. Addressed in 9241578.

- adjust tick spacing on x axes
- fixup tests

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Beautiful! Thanks for being persistent with this issue. This is a huge improvement - there still may be some cases we want to adjust, but that's pretty minor now, most cases look really good and the pan/zoom behavior (at least with rangesliders) is quite nice. 🎉 💃

@archmojarchmoj changed the title Improve ticks on axes with rangebreaksFix rangebreaks overlapping and tick positionsJun 3, 2020
@archmoj
archmoj merged commit f90690f into masterJun 3, 2020
@archmoj
archmoj deleted the rangebreaks-improve-ticks branch June 3, 2020 17:32
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugsomething broken

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Problem overlapping rangebreaks Tick labels when using hourly rangebreaks

2 participants

@archmoj@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Fix rangebreaks overlapping and tick positions by archmoj · Pull Request #4831 · plotly/plotly.js · GitHub
Skip to content

Fix rangebreaks overlapping and tick positions - #4831

Merged
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks
Jun 3, 2020
Merged

Fix rangebreaks overlapping and tick positions#4831
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks

Conversation

@archmoj

@archmojarchmoj commented May 13, 2020

Copy link
Copy Markdown
Contributor

Supersedes #4734 and fixes#4722 namely the first & second parts of #4722 (comment) i.e. when dtick is set as well as auto ticks.

demo: Before vs After

This PR also fixes#4879 by 5c8055b commit.

@plotly/plotly_js

@archmojarchmoj added this to the v1.54.2 milestone May 13, 2020
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Comment threadsrc/plots/cartesian/axes.js Outdated
var tick0 = r2l(ax.tick0);

if(ax.tickmode === 'auto' && ax.rangebreaks && ax.maskBreaks(tick0) === BADNUM) {
tick0 = moveToEndOfBreak(tick0, ax);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This still bothers me - I see it's only in auto mode but it seems like this will still have strange effects, especially if you do something unusual with the bounds of the break, like [8.75, 17.25]. That said I don't understand how we're getting the results we are in axes_breaks-dtick_auto of ticks at 9am and noon, ie alternating 3-hour and 5-hour gaps. If we're hitting this block then tick0 gets set to 9am, but then to get a tick at noon we'd need a 3-hour dtick, which would then put another tick at 3pm - not what we see. And I don't think we want a 3/5 alternation as an autotick result anyway, we should regularize that to consistent 4-hour spacing.

So a couple of image tests, like you have, are good. But I think we also want to see a bunch of jasmine tests where we just set up an axis and list the ticks (positions and labels) that result within one day. That should let us cover a whole lot more cases: auto-determined dtick from 1 hour to a day and everything between, and a few manually set dtick and tick0 values; each of these tested against each of the hourly rangebreaks I mentioned in #4722 (comment)

@archmoj

archmoj commented May 15, 2020

Copy link
Copy Markdown
ContributorAuthor

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Good call. Fixed in 4eab137 & a7633c3.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

Update:
Just pushed my attempt on improving ticks in the mode auto into this PR.

Comment threadsrc/plots/cartesian/axis_defaults.js Outdated
}

// break when found all types
if(n === 2) break;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what if the user includes two breaks of one type, THEN a break of the other type? I suppose I can theoretically imagine wanting two disjoint hour periods - a morning shift and an evening shift, with a midday break? I wouldn't worry about doing something "pretty" in this case, perhaps just set _dayHours to something like 1 or 2 so we go straight from day to hour ticks or perhaps just use the first break. But it definitely shouldn't stop us from noticing _hasDayOfWeekBreaks

And vice versa I guess... maybe someone wants to skip Sundays and Wednesdays? Again, weird, but shouldn't stop us from catching _hasHourBreaks

Comment threadsrc/plots/cartesian/axes.js Outdated
case 18: return [1, 2, 3, 6, 9];
case 20: return [1, 2, 4, 5, 10];
case 21: return [1, 3, 7];
case 22: return [1, 2, 11];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oh interesting... so just a precise list of factors of the rounded number of visible hours. I'm not sure we really want all of these, and we might want to add something intermediate for the larger primes so we don't jump straight from 1 day to 1 hour, even though we can't do it precisely uniformly. But this is a great starting point anyway, we can tweak later.

However, looking at the mocks changed in this PR it seems like there's a problem when dtick is not an even fraction of a day. For example in axes_breaks-candlestick2, dtick is 18 hours (how did that happen? I only see 9 here, I would have thought it would go to 24 after that? That doesn't matter though, there are lots of periods we want that don't divide 24 evenly, this is just an example), and as a result some days have 2 ticks (at 9:30 and 12:00) and other days have only one (at 9:30).

Trying to figure out a reasonable way to handle this, in conjunction with tick0 possibly being set manually. I think what we may need to say is: when you have hourly rangebreaks and dtick < 24h, the only piece of tick0 that we consider is the time portion and we start at that time on each new day, then increment by dtick until we get to the next day, at which point we reset the time to tick0 again, so you get ticks at the same hours in every day.

@archmojarchmoj changed the title Fix ticks with defined dtick on axes with rangebreaksImprove ticks on axes with rangebreaksJun 2, 2020
@archmoj
archmojforce-pushed the rangebreaks-improve-ticks branch from 9b45339 to c5cf45aCompareJune 3, 2020 02:01
@archmoj

Copy link
Copy Markdown
ContributorAuthor

This PR is now ready for final review.

if(ax.tickmode === 'array') nt *= 100;


ax._roughDTick = (Math.abs(rng[1] - rng[0]) - (ax._lBreaks || 0)) / nt;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking much nicer now!

I'm just noticing that the auto dtick we get depends on whether there's a break within the visible range or not, which seems weird, and seems like exactly what this - ax._lBreaks was designed to avoid. For example (back on everyone's favorite, axes_breaks-candlestick2 😅) if I zoom in while keeping a break in range I can't get dtick less than 2 hours:
Screen Shot 2020-06-02 at 10 55 55 PM

But shift the break off the edge with exactly the same scale and it snaps to 15 min:
Screen Shot 2020-06-02 at 10 57 52 PM

Is there something bad that happens if this line is left as it was?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good catch. Addressed in 9241578.

- adjust tick spacing on x axes
- fixup tests

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Beautiful! Thanks for being persistent with this issue. This is a huge improvement - there still may be some cases we want to adjust, but that's pretty minor now, most cases look really good and the pan/zoom behavior (at least with rangesliders) is quite nice. 🎉 💃

@archmojarchmoj changed the title Improve ticks on axes with rangebreaksFix rangebreaks overlapping and tick positionsJun 3, 2020
@archmoj
archmoj merged commit f90690f into masterJun 3, 2020
@archmoj
archmoj deleted the rangebreaks-improve-ticks branch June 3, 2020 17:32
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugsomething broken

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Problem overlapping rangebreaks Tick labels when using hourly rangebreaks

2 participants

@archmoj@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fix rangebreaks overlapping and tick positions by archmoj · Pull Request #4831 · plotly/plotly.js · GitHub
Skip to content

Fix rangebreaks overlapping and tick positions - #4831

Merged
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks
Jun 3, 2020
Merged

Fix rangebreaks overlapping and tick positions#4831
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks

Conversation

@archmoj

@archmojarchmoj commented May 13, 2020

Copy link
Copy Markdown
Contributor

Supersedes #4734 and fixes#4722 namely the first & second parts of #4722 (comment) i.e. when dtick is set as well as auto ticks.

demo: Before vs After

This PR also fixes#4879 by 5c8055b commit.

@plotly/plotly_js

@archmojarchmoj added this to the v1.54.2 milestone May 13, 2020
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Comment threadsrc/plots/cartesian/axes.js Outdated
var tick0 = r2l(ax.tick0);

if(ax.tickmode === 'auto' && ax.rangebreaks && ax.maskBreaks(tick0) === BADNUM) {
tick0 = moveToEndOfBreak(tick0, ax);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This still bothers me - I see it's only in auto mode but it seems like this will still have strange effects, especially if you do something unusual with the bounds of the break, like [8.75, 17.25]. That said I don't understand how we're getting the results we are in axes_breaks-dtick_auto of ticks at 9am and noon, ie alternating 3-hour and 5-hour gaps. If we're hitting this block then tick0 gets set to 9am, but then to get a tick at noon we'd need a 3-hour dtick, which would then put another tick at 3pm - not what we see. And I don't think we want a 3/5 alternation as an autotick result anyway, we should regularize that to consistent 4-hour spacing.

So a couple of image tests, like you have, are good. But I think we also want to see a bunch of jasmine tests where we just set up an axis and list the ticks (positions and labels) that result within one day. That should let us cover a whole lot more cases: auto-determined dtick from 1 hour to a day and everything between, and a few manually set dtick and tick0 values; each of these tested against each of the hourly rangebreaks I mentioned in #4722 (comment)

@archmoj

archmoj commented May 15, 2020

Copy link
Copy Markdown
ContributorAuthor

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Good call. Fixed in 4eab137 & a7633c3.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

Update:
Just pushed my attempt on improving ticks in the mode auto into this PR.

Comment threadsrc/plots/cartesian/axis_defaults.js Outdated
}

// break when found all types
if(n === 2) break;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what if the user includes two breaks of one type, THEN a break of the other type? I suppose I can theoretically imagine wanting two disjoint hour periods - a morning shift and an evening shift, with a midday break? I wouldn't worry about doing something "pretty" in this case, perhaps just set _dayHours to something like 1 or 2 so we go straight from day to hour ticks or perhaps just use the first break. But it definitely shouldn't stop us from noticing _hasDayOfWeekBreaks

And vice versa I guess... maybe someone wants to skip Sundays and Wednesdays? Again, weird, but shouldn't stop us from catching _hasHourBreaks

Comment threadsrc/plots/cartesian/axes.js Outdated
case 18: return [1, 2, 3, 6, 9];
case 20: return [1, 2, 4, 5, 10];
case 21: return [1, 3, 7];
case 22: return [1, 2, 11];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oh interesting... so just a precise list of factors of the rounded number of visible hours. I'm not sure we really want all of these, and we might want to add something intermediate for the larger primes so we don't jump straight from 1 day to 1 hour, even though we can't do it precisely uniformly. But this is a great starting point anyway, we can tweak later.

However, looking at the mocks changed in this PR it seems like there's a problem when dtick is not an even fraction of a day. For example in axes_breaks-candlestick2, dtick is 18 hours (how did that happen? I only see 9 here, I would have thought it would go to 24 after that? That doesn't matter though, there are lots of periods we want that don't divide 24 evenly, this is just an example), and as a result some days have 2 ticks (at 9:30 and 12:00) and other days have only one (at 9:30).

Trying to figure out a reasonable way to handle this, in conjunction with tick0 possibly being set manually. I think what we may need to say is: when you have hourly rangebreaks and dtick < 24h, the only piece of tick0 that we consider is the time portion and we start at that time on each new day, then increment by dtick until we get to the next day, at which point we reset the time to tick0 again, so you get ticks at the same hours in every day.

@archmojarchmoj changed the title Fix ticks with defined dtick on axes with rangebreaksImprove ticks on axes with rangebreaksJun 2, 2020
@archmoj
archmojforce-pushed the rangebreaks-improve-ticks branch from 9b45339 to c5cf45aCompareJune 3, 2020 02:01
@archmoj

Copy link
Copy Markdown
ContributorAuthor

This PR is now ready for final review.

if(ax.tickmode === 'array') nt *= 100;


ax._roughDTick = (Math.abs(rng[1] - rng[0]) - (ax._lBreaks || 0)) / nt;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking much nicer now!

I'm just noticing that the auto dtick we get depends on whether there's a break within the visible range or not, which seems weird, and seems like exactly what this - ax._lBreaks was designed to avoid. For example (back on everyone's favorite, axes_breaks-candlestick2 😅) if I zoom in while keeping a break in range I can't get dtick less than 2 hours:
Screen Shot 2020-06-02 at 10 55 55 PM

But shift the break off the edge with exactly the same scale and it snaps to 15 min:
Screen Shot 2020-06-02 at 10 57 52 PM

Is there something bad that happens if this line is left as it was?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good catch. Addressed in 9241578.

- adjust tick spacing on x axes
- fixup tests

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Beautiful! Thanks for being persistent with this issue. This is a huge improvement - there still may be some cases we want to adjust, but that's pretty minor now, most cases look really good and the pan/zoom behavior (at least with rangesliders) is quite nice. 🎉 💃

@archmojarchmoj changed the title Improve ticks on axes with rangebreaksFix rangebreaks overlapping and tick positionsJun 3, 2020
@archmoj
archmoj merged commit f90690f into masterJun 3, 2020
@archmoj
archmoj deleted the rangebreaks-improve-ticks branch June 3, 2020 17:32
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugsomething broken

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Problem overlapping rangebreaks Tick labels when using hourly rangebreaks

2 participants

@archmoj@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fix rangebreaks overlapping and tick positions by archmoj · Pull Request #4831 · plotly/plotly.js · GitHub
Skip to content

Fix rangebreaks overlapping and tick positions - #4831

Merged
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks
Jun 3, 2020
Merged

Fix rangebreaks overlapping and tick positions#4831
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks

Conversation

@archmoj

@archmojarchmoj commented May 13, 2020

Copy link
Copy Markdown
Contributor

Supersedes #4734 and fixes#4722 namely the first & second parts of #4722 (comment) i.e. when dtick is set as well as auto ticks.

demo: Before vs After

This PR also fixes#4879 by 5c8055b commit.

@plotly/plotly_js

@archmojarchmoj added this to the v1.54.2 milestone May 13, 2020
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Comment threadsrc/plots/cartesian/axes.js Outdated
var tick0 = r2l(ax.tick0);

if(ax.tickmode === 'auto' && ax.rangebreaks && ax.maskBreaks(tick0) === BADNUM) {
tick0 = moveToEndOfBreak(tick0, ax);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This still bothers me - I see it's only in auto mode but it seems like this will still have strange effects, especially if you do something unusual with the bounds of the break, like [8.75, 17.25]. That said I don't understand how we're getting the results we are in axes_breaks-dtick_auto of ticks at 9am and noon, ie alternating 3-hour and 5-hour gaps. If we're hitting this block then tick0 gets set to 9am, but then to get a tick at noon we'd need a 3-hour dtick, which would then put another tick at 3pm - not what we see. And I don't think we want a 3/5 alternation as an autotick result anyway, we should regularize that to consistent 4-hour spacing.

So a couple of image tests, like you have, are good. But I think we also want to see a bunch of jasmine tests where we just set up an axis and list the ticks (positions and labels) that result within one day. That should let us cover a whole lot more cases: auto-determined dtick from 1 hour to a day and everything between, and a few manually set dtick and tick0 values; each of these tested against each of the hourly rangebreaks I mentioned in #4722 (comment)

@archmoj

archmoj commented May 15, 2020

Copy link
Copy Markdown
ContributorAuthor

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Good call. Fixed in 4eab137 & a7633c3.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

Update:
Just pushed my attempt on improving ticks in the mode auto into this PR.

Comment threadsrc/plots/cartesian/axis_defaults.js Outdated
}

// break when found all types
if(n === 2) break;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what if the user includes two breaks of one type, THEN a break of the other type? I suppose I can theoretically imagine wanting two disjoint hour periods - a morning shift and an evening shift, with a midday break? I wouldn't worry about doing something "pretty" in this case, perhaps just set _dayHours to something like 1 or 2 so we go straight from day to hour ticks or perhaps just use the first break. But it definitely shouldn't stop us from noticing _hasDayOfWeekBreaks

And vice versa I guess... maybe someone wants to skip Sundays and Wednesdays? Again, weird, but shouldn't stop us from catching _hasHourBreaks

Comment threadsrc/plots/cartesian/axes.js Outdated
case 18: return [1, 2, 3, 6, 9];
case 20: return [1, 2, 4, 5, 10];
case 21: return [1, 3, 7];
case 22: return [1, 2, 11];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oh interesting... so just a precise list of factors of the rounded number of visible hours. I'm not sure we really want all of these, and we might want to add something intermediate for the larger primes so we don't jump straight from 1 day to 1 hour, even though we can't do it precisely uniformly. But this is a great starting point anyway, we can tweak later.

However, looking at the mocks changed in this PR it seems like there's a problem when dtick is not an even fraction of a day. For example in axes_breaks-candlestick2, dtick is 18 hours (how did that happen? I only see 9 here, I would have thought it would go to 24 after that? That doesn't matter though, there are lots of periods we want that don't divide 24 evenly, this is just an example), and as a result some days have 2 ticks (at 9:30 and 12:00) and other days have only one (at 9:30).

Trying to figure out a reasonable way to handle this, in conjunction with tick0 possibly being set manually. I think what we may need to say is: when you have hourly rangebreaks and dtick < 24h, the only piece of tick0 that we consider is the time portion and we start at that time on each new day, then increment by dtick until we get to the next day, at which point we reset the time to tick0 again, so you get ticks at the same hours in every day.

@archmojarchmoj changed the title Fix ticks with defined dtick on axes with rangebreaksImprove ticks on axes with rangebreaksJun 2, 2020
@archmoj
archmojforce-pushed the rangebreaks-improve-ticks branch from 9b45339 to c5cf45aCompareJune 3, 2020 02:01
@archmoj

Copy link
Copy Markdown
ContributorAuthor

This PR is now ready for final review.

if(ax.tickmode === 'array') nt *= 100;


ax._roughDTick = (Math.abs(rng[1] - rng[0]) - (ax._lBreaks || 0)) / nt;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking much nicer now!

I'm just noticing that the auto dtick we get depends on whether there's a break within the visible range or not, which seems weird, and seems like exactly what this - ax._lBreaks was designed to avoid. For example (back on everyone's favorite, axes_breaks-candlestick2 😅) if I zoom in while keeping a break in range I can't get dtick less than 2 hours:
Screen Shot 2020-06-02 at 10 55 55 PM

But shift the break off the edge with exactly the same scale and it snaps to 15 min:
Screen Shot 2020-06-02 at 10 57 52 PM

Is there something bad that happens if this line is left as it was?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good catch. Addressed in 9241578.

- adjust tick spacing on x axes
- fixup tests

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Beautiful! Thanks for being persistent with this issue. This is a huge improvement - there still may be some cases we want to adjust, but that's pretty minor now, most cases look really good and the pan/zoom behavior (at least with rangesliders) is quite nice. 🎉 💃

@archmojarchmoj changed the title Improve ticks on axes with rangebreaksFix rangebreaks overlapping and tick positionsJun 3, 2020
@archmoj
archmoj merged commit f90690f into masterJun 3, 2020
@archmoj
archmoj deleted the rangebreaks-improve-ticks branch June 3, 2020 17:32
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugsomething broken

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Problem overlapping rangebreaks Tick labels when using hourly rangebreaks

2 participants

@archmoj@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Fix rangebreaks overlapping and tick positions by archmoj · Pull Request #4831 · plotly/plotly.js · GitHub
Skip to content

Fix rangebreaks overlapping and tick positions - #4831

Merged
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks
Jun 3, 2020
Merged

Fix rangebreaks overlapping and tick positions#4831
archmoj merged 22 commits into
masterfrom
rangebreaks-improve-ticks

Conversation

@archmoj

@archmojarchmoj commented May 13, 2020

Copy link
Copy Markdown
Contributor

Supersedes #4734 and fixes#4722 namely the first & second parts of #4722 (comment) i.e. when dtick is set as well as auto ticks.

demo: Before vs After

This PR also fixes#4879 by 5c8055b commit.

@plotly/plotly_js

@archmojarchmoj added this to the v1.54.2 milestone May 13, 2020
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Comment threadsrc/plots/cartesian/axes.js Outdated
var tick0 = r2l(ax.tick0);

if(ax.tickmode === 'auto' && ax.rangebreaks && ax.maskBreaks(tick0) === BADNUM) {
tick0 = moveToEndOfBreak(tick0, ax);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This still bothers me - I see it's only in auto mode but it seems like this will still have strange effects, especially if you do something unusual with the bounds of the break, like [8.75, 17.25]. That said I don't understand how we're getting the results we are in axes_breaks-dtick_auto of ticks at 9am and noon, ie alternating 3-hour and 5-hour gaps. If we're hitting this block then tick0 gets set to 9am, but then to get a tick at noon we'd need a 3-hour dtick, which would then put another tick at 3pm - not what we see. And I don't think we want a 3/5 alternation as an autotick result anyway, we should regularize that to consistent 4-hour spacing.

So a couple of image tests, like you have, are good. But I think we also want to see a bunch of jasmine tests where we just set up an axis and list the ticks (positions and labels) that result within one day. That should let us cover a whole lot more cases: auto-determined dtick from 1 hour to a day and everything between, and a few manually set dtick and tick0 values; each of these tested against each of the hourly rangebreaks I mentioned in #4722 (comment)

@archmoj

archmoj commented May 15, 2020

Copy link
Copy Markdown
ContributorAuthor

Why do both of the new baselines have an "18:27" tick right at the end?
Screen Shot 2020-05-14 at 6 55 35 PM

Good call. Fixed in 4eab137 & a7633c3.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

@archmoj

Copy link
Copy Markdown
ContributorAuthor

@alexcjohnson FYI - I am still working on a dev branch to address the second part of #4722 (comment).
But I'd rather opening a separate PR after this one (which fixed few bugs) possibly merged.

Update:
Just pushed my attempt on improving ticks in the mode auto into this PR.

Comment threadsrc/plots/cartesian/axis_defaults.js Outdated
}

// break when found all types
if(n === 2) break;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what if the user includes two breaks of one type, THEN a break of the other type? I suppose I can theoretically imagine wanting two disjoint hour periods - a morning shift and an evening shift, with a midday break? I wouldn't worry about doing something "pretty" in this case, perhaps just set _dayHours to something like 1 or 2 so we go straight from day to hour ticks or perhaps just use the first break. But it definitely shouldn't stop us from noticing _hasDayOfWeekBreaks

And vice versa I guess... maybe someone wants to skip Sundays and Wednesdays? Again, weird, but shouldn't stop us from catching _hasHourBreaks

Comment threadsrc/plots/cartesian/axes.js Outdated
case 18: return [1, 2, 3, 6, 9];
case 20: return [1, 2, 4, 5, 10];
case 21: return [1, 3, 7];
case 22: return [1, 2, 11];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oh interesting... so just a precise list of factors of the rounded number of visible hours. I'm not sure we really want all of these, and we might want to add something intermediate for the larger primes so we don't jump straight from 1 day to 1 hour, even though we can't do it precisely uniformly. But this is a great starting point anyway, we can tweak later.

However, looking at the mocks changed in this PR it seems like there's a problem when dtick is not an even fraction of a day. For example in axes_breaks-candlestick2, dtick is 18 hours (how did that happen? I only see 9 here, I would have thought it would go to 24 after that? That doesn't matter though, there are lots of periods we want that don't divide 24 evenly, this is just an example), and as a result some days have 2 ticks (at 9:30 and 12:00) and other days have only one (at 9:30).

Trying to figure out a reasonable way to handle this, in conjunction with tick0 possibly being set manually. I think what we may need to say is: when you have hourly rangebreaks and dtick < 24h, the only piece of tick0 that we consider is the time portion and we start at that time on each new day, then increment by dtick until we get to the next day, at which point we reset the time to tick0 again, so you get ticks at the same hours in every day.

@archmojarchmoj changed the title Fix ticks with defined dtick on axes with rangebreaksImprove ticks on axes with rangebreaksJun 2, 2020
@archmoj
archmojforce-pushed the rangebreaks-improve-ticks branch from 9b45339 to c5cf45aCompareJune 3, 2020 02:01
@archmoj

Copy link
Copy Markdown
ContributorAuthor

This PR is now ready for final review.

if(ax.tickmode === 'array') nt *= 100;


ax._roughDTick = (Math.abs(rng[1] - rng[0]) - (ax._lBreaks || 0)) / nt;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking much nicer now!

I'm just noticing that the auto dtick we get depends on whether there's a break within the visible range or not, which seems weird, and seems like exactly what this - ax._lBreaks was designed to avoid. For example (back on everyone's favorite, axes_breaks-candlestick2 😅) if I zoom in while keeping a break in range I can't get dtick less than 2 hours:
Screen Shot 2020-06-02 at 10 55 55 PM

But shift the break off the edge with exactly the same scale and it snaps to 15 min:
Screen Shot 2020-06-02 at 10 57 52 PM

Is there something bad that happens if this line is left as it was?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good catch. Addressed in 9241578.

- adjust tick spacing on x axes
- fixup tests

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Beautiful! Thanks for being persistent with this issue. This is a huge improvement - there still may be some cases we want to adjust, but that's pretty minor now, most cases look really good and the pan/zoom behavior (at least with rangesliders) is quite nice. 🎉 💃

@archmojarchmoj changed the title Improve ticks on axes with rangebreaksFix rangebreaks overlapping and tick positionsJun 3, 2020
@archmoj
archmoj merged commit f90690f into masterJun 3, 2020
@archmoj
archmoj deleted the rangebreaks-improve-ticks branch June 3, 2020 17:32
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugsomething broken

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Problem overlapping rangebreaks Tick labels when using hourly rangebreaks

2 participants

@archmoj@alexcjohnson