Skip to content
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

asinh colorbar tick locator with simple_norm #11607

Open
keflavich opened this issue Apr 19, 2021 · 4 comments
Open

asinh colorbar tick locator with simple_norm #11607

keflavich opened this issue Apr 19, 2021 · 4 comments

Comments

@keflavich
Copy link
Contributor

When using simple_norm with log and asinh stretch, the tick locations frequently come out awkward at best.

I'd like to see:

  • some documentation indicating how to set more reasonable tick locations
  • perhaps custom colorbar (?) instantiators or tools that can help achieve these.

Perhaps we should use matplotlib's tick locators (https://matplotlib.org/3.1.1/gallery/ticks_and_spines/tick-locators.html) for this?

Some example awkward colorbars:
image
image

The latter one originally had no ticks below 50! I added one with the hack:

    ticklabels = cb.ax.get_ymajorticklabels()
    ticks = list(cb.get_ticks())
    minVal = norm.vmin
    newticks = [minVal, ] + ticks
    newticklabels = [f"{minVal:0.2f}",] + [x.get_text() for x in ticklabels]
    cb.set_ticks(newticks)
    cb.set_ticklabels(newticklabels)

But that's still far from optimal. I'd like something that approximately linearly spaces ticks, but ideally with more aesthetic rounding choices.

@pllim
Copy link
Member

pllim commented Apr 19, 2021

Do you have a fully but minimally reproducible code? I don't see any astropy usage in the current snippet.

@keflavich
Copy link
Contributor Author

keflavich commented Apr 19, 2021

import numpy as np, pylab as pl
from astropy.visualization import simple_norm
x = np.random.randn(100,100) + 5
x[20,20] = 100
norm = simple_norm(x, stretch='asinh')
pl.imshow(x, norm=norm)
pl.colorbar()

image

@pllim pllim changed the title asinh colorbar tick locator asinh colorbar tick locator with simple_norm Apr 19, 2021
@keflavich
Copy link
Contributor Author

workaround:

    arcsinh_range = np.arcsinh(norm.vmin), np.arcsinh(norm.vmax)
    new_ticks = np.sinh(np.linspace(*arcsinh_range, 10))

    # this part is essential for picking quasi-reasonable values.  
    rounded = [np.format_float_positional(x, 2, unique=False, fractional=False, trim='k') for x in new_ticks]
    cb.set_ticks(list(map(float, rounded)))
    cb.set_ticklabels([x.rstrip('.') for x in rounded])

This won't work in all cases, but it captures several cases half-decently.

@keflavich
Copy link
Contributor Author

Further hackery:

def determine_asinh_ticklocs(vmin, vmax, nticks):
    arcsinh_range = np.arcsinh(vmin), np.arcsinh(vmax)
    new_ticks = np.sinh(np.linspace(*arcsinh_range, nticks))
    rounded = [np.format_float_positional(x, 2, unique=False, fractional=False, trim='k') for x in new_ticks]

    rounded_loc = np.array(rounded).astype('float')
    if rounded_loc.min() < 0 and rounded_loc.max() > 0:
        zero_index = np.argmin(np.abs(rounded_loc))
        rounded_loc[zero_index] = 0
        rounded[zero_index] = 0

        if zero_index == 0:
            rounded_loc = np.array([vmin] + list(rounded_loc))
            rounded = [np.format_float_positional(vmin, 2, unique=False, fractional=False, trim='k')] + rounded

    if rounded_loc[0] < vmin:
        rounded_loc[0] = vmin

    if rounded_loc[-1] > vmax:
        rounded_loc[-1] = vmax
    else:
        rounded_loc[-1] = vmax
        rounded[-1] = np.format_float_positional(vmax, 2, unique=False, fractional=False, trim='k')
    
    rounded = [str(x).rstrip('.') for x in rounded]

    return rounded_loc, rounde

This still isn't great, but it guarantees that 0 is labeled if 0 is in range, and that the minimum & maximum are shown.

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

No branches or pull requests

2 participants