I'm having difficulty getting custom tick locations to display on a twinned axis set to log scale. The tick locations display fine on the original log-scale axis, and the tick locations display fine if the twinned axis is not set to log scale. My desired outcome is to have the normal log axis ticks on the bottom X axis (displayed in the right-side plot), and have the custom tick locations displayed on the upper twinned axis at their appropriate log-scale location (locations shown on the bottom left plot, but needed on top of plot).
Other solutions I've come across don't fix this issue for me. Are there other ways to control the tick locations and labels? (currently running matplotlib version 3.7.1)
import matplotlib.pyplot as plt
## Locations for upper ticks
tick_locations=[3.9, 63, 250, 500]
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(7,3))
##Shared x limits
xlims=(10**-1, 2000)
## Twin the axes
sizeax0 = ax[0].twiny()
sizeax1 = ax[1].twiny()
## Plot 1 --------------------
## Setting tick locations on twinned log X axis fails
sizeax0.set_xticks(ticks=tick_locations,
labels=["a", "b", "c", "d"])
sizeax0.set(xlim=(xlims[0], xlims[1]),
xscale="log",
title="Top should look like the bottom axis")
## Setting tick locations on original log X axis works
ax[0].set(xscale="log",
xlim=(xlims[0], xlims[1]))
ax[0].grid(which="major")
ax[0].set_xticks(ticks=tick_locations,
labels=["a", "b", "c", "d"])
## Removing the minor ticks between custom tick locations
ax[0].get_xaxis().set_tick_params(which='minor', size=0, width=0)
## Plot 2 --------------------
## Setting tick locations on twinned non-log X axis works
sizeax1.set_xticks(ticks=[3.9, 63, 250, 500],
labels=["a", "b", "c", "d"])
sizeax1.set(xlim=(xlims[0], xlims[1]),
title="Ticks aren't log-spaced")
ax[1].set(xscale="log",
xlim=(xlims[0], xlims[1]),
xlabel="Bottom axis should look like this")
ax[1].grid(which="major")
plt.tight_layout()
plt.show()
There does appear to be a issue with twinx/twiny and log axis. There is a ticket her, although not sure if it is fixed. What I was able to do is, for the top (secondary) x-axis, manually do what the xscale='log'
is supposed to do. In your code, I updated the few lines below PLOT 1 as shown below. See if this will work for you. Another important thing to note is that, your x-data for which the top axis ticks are for needs to ALSO be plotted using np.log10()
. As the plot doesn't have data, it is not included. Hope this helps.
## Plot 1 --------------------
## Setting tick locations on twinned log X axis fails
### Updated code - Used log10 to manually set tick locations
sizeax0.set_xticks(ticks=np.log10(tick_locations))
sizeax0.set_xticklabels(labels=["a", "b", "c", "d"])
### Removed xscale = "log" and used np.log10() for both xlim entries
sizeax0.set(xlim=(np.log10(xlims[0]), np.log10(xlims[1])),
# xscale="log",
title="Top NOW looks like the bottom axis")
### -- Rest of your code