Skip to content

adds rule to select fewer ticks in sqrt scale for bokeh and plotly#189

Merged
aloctavodia merged 4 commits intoarviz-devs:mainfrom
The-Broken-Keyboard:fewer_ticks_in_sqrt_scale
Mar 28, 2025
Merged

adds rule to select fewer ticks in sqrt scale for bokeh and plotly#189
aloctavodia merged 4 commits intoarviz-devs:mainfrom
The-Broken-Keyboard:fewer_ticks_in_sqrt_scale

Conversation

@The-Broken-Keyboard
Copy link
Copy Markdown
Contributor

@The-Broken-Keyboard The-Broken-Keyboard commented Mar 22, 2025

closes #184

Instead of adding all integer ticks within range [0,max_y_value], new rule adds fewer ticks in same range.
The rule is similar to Matplotlib's autolocator's rule, it calculates the possible no. of ticks first in the given range, then it clips that value between 1 to 5. Then based on the number of ticks it calculates step size to put ticks across the axis.

By default the number of ticks is 5 ( didn't keep it 9, which matplotlib has, because in square root scale higher value ticks are placed more closer so it looks little congested for more number of ticks ).

Bokeh:

image

Plotly:

image


📚 Documentation preview 📚: https://arviz-plots--189.org.readthedocs.build/en/189/

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 22, 2025

Codecov Report

Attention: Patch coverage is 9.09091% with 10 lines in your changes missing coverage. Please review.

Project coverage is 72.49%. Comparing base (6265a5e) to head (c4adac4).

Files with missing lines Patch % Lines
src/arviz_plots/backend/plotly/__init__.py 14.28% 6 Missing ⚠️
src/arviz_plots/backend/bokeh/__init__.py 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #189      +/-   ##
==========================================
- Coverage   72.52%   72.49%   -0.03%     
==========================================
  Files          35       35              
  Lines        4026     4029       +3     
==========================================
+ Hits         2920     2921       +1     
- Misses       1106     1108       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@aloctavodia
Copy link
Copy Markdown
Contributor

This will still be problematic if frequencies have large values, for instance

dt = azb.from_dict({
'observed_data': {"obs":pz.Poisson(2).rvs(1000)},
'posterior_predictive': {"obs":pz.Poisson(2).rvs((2, 1000, 1000))}
})

@The-Broken-Keyboard
Copy link
Copy Markdown
Contributor Author

Yeah, true. I just realised that it will be problematic if maximum y value is high.

To handle this, Can we have a default fix number of ticks which we can determine dynamically between minimum y value and maximum y value? So even for high values, the number of ticks can be fixed.

Or else, we can have a dynamic rule which will determine the good number of ticks for a given range of values. Then determining those ticks won't be a difficult task to do....

What do you suggest @aloctavodia ?

@aloctavodia
Copy link
Copy Markdown
Contributor

It is probably a good idea to check what matplotlib does by default and implement something similar.

@The-Broken-Keyboard
Copy link
Copy Markdown
Contributor Author

The-Broken-Keyboard commented Mar 25, 2025

Heyy @aloctavodia
I just went through the implementation in Matplotlib ( reference link : https://matplotlib.org/stable/api/ticker_api.html#matplotlib.ticker.AutoLocator ), they have an upper limit for no. of ticks which is 9 and lower limit for no. of ticks which is 1. They compute no. of integral intervals in the given range of y values ( by using function get_tick_space ), if they fall between 1-9 then they place those many ticks. If it goes above or below limits then they clip those values on 1 or 9 ( as you can see in below given screenshot ) . This is similar approach to what I suggested, either to fix no. of ticks or to find optimal no. of ticks based upon the given y value range. Let me know what would you prefer to do.....

image

@aloctavodia
Copy link
Copy Markdown
Contributor

Fixing the number of ticks like Matplotlib seems reasonable.

Copy link
Copy Markdown
Contributor

@aloctavodia aloctavodia left a comment

Choose a reason for hiding this comment

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

Plotly is missing the highest ytick, and sometimes cropping the highest value . See for example

dt = azb.from_dict({
'observed_data': {"obs":pz.Poisson(2).rvs(100, random_state=1)},
'posterior_predictive': {"obs":pz.Poisson(2).rvs((2, 1000, 100), random_state=1)}
})

Comment on lines +61 to +66
num_ticks = 5
num_ticks = min(num_ticks, math.ceil(((y_max * y_max) - (y_min * y_min)) / 2))
step_size = round(((y_max * y_max) - (y_min * y_min)) / num_ticks)
start_tick = round(y_min * y_min)
end_tick = step_size * num_ticks

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
num_ticks = 5
num_ticks = min(num_ticks, math.ceil(((y_max * y_max) - (y_min * y_min)) / 2))
step_size = round(((y_max * y_max) - (y_min * y_min)) / num_ticks)
start_tick = round(y_min * y_min)
end_tick = step_size * num_ticks
num_ticks = 5
num_ticks = min(num_ticks, math.ceil((y_max**2 - y_min**2) / 2))
step_size = math.ceil((y_max**2 - y_min**2) / num_ticks)
start_tick = math.ceil(y_min**2)
end_tick = step_size * num_ticks

tickvals_transformed = []
for i in range(int(round(y_max * y_max)) + 1):
tickvals_transformed.append(np.sqrt(i))
for i in range(start_tick, end_tick, step_size):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
for i in range(start_tick, end_tick, step_size):
tickvals_transformed = [i**0.5 for i in range(start_tick, end_tick, step_size)]

Comment on lines +46 to +50
num_ticks = 5
num_ticks = min(num_ticks, math.ceil(max_y / 2))
step_size = round(math.ceil(max_y) / num_ticks)
end_tick = num_ticks * step_size
start_tick = 0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
num_ticks = 5
num_ticks = min(num_ticks, math.ceil(max_y / 2))
step_size = round(math.ceil(max_y) / num_ticks)
end_tick = num_ticks * step_size
start_tick = 0
num_ticks = min(5, math.ceil(max_y / 2))
step_size = round(math.ceil(max_y) / num_ticks)
end_tick = num_ticks * step_size
ticks = [i**0.5 for i in range(0, end_tick + 1, step_size)]

ticks = []
if max_y > 0:
for i in range(math.ceil(max_y) + 1):
for i in range(start_tick, end_tick + 1, step_size):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
for i in range(start_tick, end_tick + 1, step_size):

@aloctavodia
Copy link
Copy Markdown
Contributor

One more details. There is a lot of blank space below 0 for plotly. The plot should start at 0 like it does fro bokeh and matplotlib

imagen

@The-Broken-Keyboard
Copy link
Copy Markdown
Contributor Author

The-Broken-Keyboard commented Mar 27, 2025

One more details. There is a lot of blank space below 0 for plotly. The plot should start at 0 like it does fro bokeh and matplotlib

imagen

Yeah, I kept that knowingly because the circular dots in plotly ( which are little bigger in size than a normal dot ) would get cut if they fall on value 0. I can remove it or I can reduce the gap as well. Whatever you suggest @aloctavodia .

like this would happen without space:
image

In Bokeh and Matplotlib the dots are not circular with bigger size so it looks good there.

@aloctavodia
Copy link
Copy Markdown
Contributor

could you please update the images in the PR description?

@aloctavodia aloctavodia merged commit 9f0bb91 into arviz-devs:main Mar 28, 2025
3 checks passed
@The-Broken-Keyboard
Copy link
Copy Markdown
Contributor Author

@aloctavodia actually I am currently in a class so couldn't update image when you asked.
I will update it once I get out of this class. Sorry for delay.

@aloctavodia
Copy link
Copy Markdown
Contributor

Sure, no rush. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Select fewer y-ticks values in sqrt scale for Plotly & Bokeh

3 participants