Scaled Secondary Axis that is Slaved to Primary

All-

I frequently find myself trying to create plots that use a secondary axis
to indicate data in a second set of units. For example, I might plot a data
set with an x-axis in data number (e.g. the output of an analog to digital
converter), and then wish to display the calibrated units on a secondary
x-axis (e.g. volts).

There are quite a few examples that do this by creating a secondary axis
using twiny(), and then setting the limits of the secondary x-axis to the
scaled limits of the primary, and possibly setting the ticks to line up as
well.

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm

f, ax = plt.subplots(1)
x_dn = np.arange(4096)
y = norm.pdf(x_dn, 2048, 64)

v = lambda x: x*5.0/4096

ax.plot(x_dn, y)
ax.grid(True)
ax_top = ax.twiny()
ax_top.grid(True)
ax_top.set_xticks([v(x) for x in ax.get_xticks()]) # optional, aligns the
grids
ax_top.set_xlim([v(x) for x in ax.get_xlim()])

This isn't too painful if you're only doing it once. However, if you
subsequently want to change the limits (from the command line) you have to
explicitly set the limits of both axes or they will become out of sync
(aside: they also can get out of sync if you set the secondary limits
before the ticks, because setting the ticks can change the limits!). If you
do set the ticks to line up the grids, then you also have to recompute
those for the secondary axis.

ax.set_xlim([1500, 2500]) # now they're out of sync
ax_top.set_xticks([v(x) for x in ax.get_xticks()]) # ticks correct, but in
wrong places
ax_top.set_xlim([v(x) for x in ax.get_xlim()]) # all's well again.

It just seems like there ought to be a better way. I apologize if it's out
there and I missed it.

Thanks,
--Chad
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20180308/6a55aa21/attachment.html>

Hi Chad,

Tom Caswell answered a similar question from me last year:
https://mail.python.org/pipermail/matplotlib-users/2017-May/000888.html
Look towards the very end of the example to see how to do arbitrary
things automatically when xlims and ylims change.
HTH!

Juan.

···

On Fri, Mar 9, 2018, at 2:51 AM, Chad Parker wrote:

All-
I frequently find myself trying to create plots that use a secondary
axis to indicate data in a second set of units. For example, I might
plot a data set with an x-axis in data number (e.g. the output of an
analog to digital converter), and then wish to display the calibrated
units on a secondary x-axis (e.g. volts).>
There are quite a few examples that do this by creating a secondary
axis using twiny(), and then setting the limits of the secondary x-
axis to the scaled limits of the primary, and possibly setting the
ticks to line up as well.> import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm

f, ax = plt.subplots(1)
x_dn = np.arange(4096)
y = norm.pdf(x_dn, 2048, 64)
v = lambda x: x*5.0/4096

ax.plot(x_dn, y)
ax.grid(True)
ax_top = ax.twiny()
ax_top.grid(True)
ax_top.set_xticks([v(x) for x in ax.get_xticks()]) # optional, aligns
the grids> ax_top.set_xlim([v(x) for x in ax.get_xlim()])

This isn't too painful if you're only doing it once. However, if you
subsequently want to change the limits (from the command line) you
have to explicitly set the limits of both axes or they will become out
of sync (aside: they also can get out of sync if you set the secondary
limits before the ticks, because setting the ticks can change the
limits!). If you do set the ticks to line up the grids, then you also
have to recompute those for the secondary axis.> ax.set_xlim([1500, 2500]) # now they're out of sync
ax_top.set_xticks([v(x) for x in ax.get_xticks()]) # ticks correct,
but in wrong places> ax_top.set_xlim([v(x) for x in ax.get_xlim()]) # all's well again.
It just seems like there ought to be a better way. I apologize if it's
out there and I missed it.> Thanks,
--Chad
_________________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
https://mail.python.org/mailman/listinfo/matplotlib-users

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20180309/787b5824/attachment.html>

I believe I saw an excellent example of this using Bokeh. There was a map,
and you could drag a rectangle in it and have that area show up in a linked
box. Also could move the rectangle around. Sorry for lack of information -
it's on my work computer and I'm not there. I realize this does not use
matplotlib, but it's good to know about alternative ways of doing things.

···

----
Glenn Nelson in Santa Cruz
social: http://google.com/+GlennNelson
see my Kite Aerial Photos at http://www.glenn-nelson.us/kap

On Thu, Mar 8, 2018 at 7:51 AM, Chad Parker <parker.charles at gmail.com> wrote:

All-

I frequently find myself trying to create plots that use a secondary axis
to indicate data in a second set of units. For example, I might plot a data
set with an x-axis in data number (e.g. the output of an analog to digital
converter), and then wish to display the calibrated units on a secondary
x-axis (e.g. volts).

There are quite a few examples that do this by creating a secondary axis
using twiny(), and then setting the limits of the secondary x-axis to the
scaled limits of the primary, and possibly setting the ticks to line up as
well.

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm

f, ax = plt.subplots(1)
x_dn = np.arange(4096)
y = norm.pdf(x_dn, 2048, 64)

v = lambda x: x*5.0/4096

ax.plot(x_dn, y)
ax.grid(True)
ax_top = ax.twiny()
ax_top.grid(True)
ax_top.set_xticks([v(x) for x in ax.get_xticks()]) # optional, aligns the
grids
ax_top.set_xlim([v(x) for x in ax.get_xlim()])

This isn't too painful if you're only doing it once. However, if you
subsequently want to change the limits (from the command line) you have to
explicitly set the limits of both axes or they will become out of sync
(aside: they also can get out of sync if you set the secondary limits
before the ticks, because setting the ticks can change the limits!). If you
do set the ticks to line up the grids, then you also have to recompute
those for the secondary axis.

ax.set_xlim([1500, 2500]) # now they're out of sync
ax_top.set_xticks([v(x) for x in ax.get_xticks()]) # ticks correct, but
in wrong places
ax_top.set_xlim([v(x) for x in ax.get_xlim()]) # all's well again.

It just seems like there ought to be a better way. I apologize if it's out
there and I missed it.

Thanks,
--Chad

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
https://mail.python.org/mailman/listinfo/matplotlib-users

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20180316/b312b1a7/attachment.html>