double tick labels (bottom and top, but with different labels)

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

double tick labels (bottom and top, but with different labels)

Pierre Haessig

Hello,


I'd like to know if it's possible to get a sort of double tick labeling (e.g. bottom and top), but with different labels. One way to think of my use case is that there are two different units for the x data (or more precisely in my case, I've two different x quantities which are bound by a linear relationship).

The result I'd like is the right part of the attached image (it's a Gimp-edited mockup composition of the two actual plots on the left).

I've tried to play with the double labeling of a single axe. Indeed, the following two calls put the double labeling

ax1.xaxis.set_ticks_position('both')
ax1.xaxis.set_tick_params(labeltop=True)

However, when I want to alter only the top labels using

for tick, l in zip(ax1.xaxis.get_major_ticks(), l2):
    tick.set_label2(l)

I get no visible change on the plot. (full script attached). Did I need to call some update ?

Did I miss something with the proper way to call Tick.set_label2?

Looking at the source code of ax1.xaxis.set_ticklabels, there is something I don't get. First it sets a FixedFormatter(ticklabels), and then it sets label1 and/or label2 for each Tick object. So in the end, where is the text coming from?


Also, to complement the second series of tick labels, I'd like a second axis label as well. However, I only know ax.xaxis.set_label_position('top') to move xlabel to the top, not to get a 2nd one...


As an alternative approach, I see twinx. I didn't try it yet, because I feel like my objective is not of the objective of twinx (e.g. I'm plotting only a single dataset, not two). However, I suspect it's possible to 'bend" twinx to get what I want. What do you think.


Thank you in advance for your ideas.


Best,

Pierre



_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users

double_labels_mockup.png (92K) Download Attachment
DoubleTicksTest.py (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: double tick labels (bottom and top, but with different labels)

vincent.adrien@gmail.com
Hi Pierre,

I am not sure that label2 can be used for what you want to do. See for
example: https://github.com/matplotlib/matplotlib/issues/8181 . If it
can, I would be eager to know too :)! But I have currently little hopes
that there is an easy *dedicated* method available right now, as Jody K.
recently opened an issue on the GitHub tracker, about a very similar
problem: https://github.com/matplotlib/matplotlib/issues/10976

At least, as  a workaround, a twinned axis allows to get things
reasonably working without too much hassle (I think). Here is an example
that uses uses `FuncFormatter` and seems to be OK, even when
interactively playing with it.
```python
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter, MultipleLocator

fig, ax = plt.subplots(num="example_pierre", clear=True)

# A dummy plot
xx, yy = [10, 20, 30], [1, 4, 9]
ax.plot(xx, yy)
ax.set_ylabel("An y-label")
ax.set_xlabel("Quantity $x$")
ax.xaxis.set_major_locator(MultipleLocator(10))

# Secondary labelling with twiny
k = 5
ax1 = ax.twiny()
ax1.plot(xx, yy, ls="", color="none")  # dummy trace
ax1.xaxis.set_major_locator(ax.xaxis.get_major_locator())
ax1.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: f"{k*x:g}"))
ax1.set_xlabel(f"{k} times quantity $x$")

fig.show()
fig.savefig(fig.get_label() + ".pdf")
```

Hopefully this helps a bit.

Best
Adrien

PS: If there are better solution to share the ticker and the view
limits, I am interesting to know about it :).


Le 25/04/2018 à 05:34, Pierre Haessig a écrit :

> Hello,
>
>
> I'd like to know if it's possible to get a sort of double tick labeling
> (e.g. bottom and top), but with different labels. One way to think of my
> use case is that there are two different units for the x data (or more
> precisely in my case, I've two different x quantities which are bound by
> a linear relationship).
>
> The result I'd like is the right part of the attached image (it's a
> Gimp-edited mockup composition of the two actual plots on the left).
>
> I've tried to play with the double labeling of a single axe. Indeed, the
> following two calls put the double labeling
>
>     ax1.xaxis.set_ticks_position('both')
>     ax1.xaxis.set_tick_params(labeltop=True)
>
> However, when I want to alter only the top labels using
>
>     for tick, l in zip(ax1.xaxis.get_major_ticks(), l2):
>         tick.set_label2(l)
>
> I get no visible change on the plot. (full script attached). Did I need
> to call some update ?
>
> Did I miss something with the proper way to call Tick.set_label2?
>
> Looking at the source code of ax1.xaxis.set_ticklabels, there is
> something I don't get. First it sets a FixedFormatter(ticklabels), and
> then it sets label1 and/or label2 for each Tick object. So in the end,
> where is the text coming from?
>
>
> Also, to complement the second series of tick labels, I'd like a second
> axis label as well. However, I only know
> ax.xaxis.set_label_position('top') to move xlabel to the top, not to get
> a 2nd one...
>
>
> As an alternative approach, I see twinx. I didn't try it yet, because I
> feel like my objective is not of the objective of twinx (e.g. I'm
> plotting only a single dataset, not two). However, I suspect it's
> possible to 'bend" twinx to get what I want. What do you think.
>
>
> Thank you in advance for your ideas.
>
>
> Best,
>
> Pierre
>
>
>
>
> _______________________________________________
> Matplotlib-users mailing list
> [hidden email]
> https://mail.python.org/mailman/listinfo/matplotlib-users
>

_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users

example_pierre.pdf (18K) Download Attachment
example_pierre.py (703 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: double tick labels (bottom and top, but with different labels)

Jody Klymak
Yes, this is the goal and will be implimented for 3.0 if the approach is accepted.  See also https://github.com/matplotlib/matplotlib/issues/11005  Comments very welcome.  But for now Adrien’s workaround is the best we have.  

Cheers,   Jody

On 25 Apr 2018, at 08:52, [hidden email] wrote:

Hi Pierre,

I am not sure that label2 can be used for what you want to do. See for
example: https://github.com/matplotlib/matplotlib/issues/8181 . If it
can, I would be eager to know too :)! But I have currently little hopes
that there is an easy *dedicated* method available right now, as Jody K.
recently opened an issue on the GitHub tracker, about a very similar
problem: https://github.com/matplotlib/matplotlib/issues/10976

At least, as  a workaround, a twinned axis allows to get things
reasonably working without too much hassle (I think). Here is an example
that uses uses `FuncFormatter` and seems to be OK, even when
interactively playing with it.
```python
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter, MultipleLocator

fig, ax = plt.subplots(num="example_pierre", clear=True)

# A dummy plot
xx, yy = [10, 20, 30], [1, 4, 9]
ax.plot(xx, yy)
ax.set_ylabel("An y-label")
ax.set_xlabel("Quantity $x$")
ax.xaxis.set_major_locator(MultipleLocator(10))

# Secondary labelling with twiny
k = 5
ax1 = ax.twiny()
ax1.plot(xx, yy, ls="", color="none")  # dummy trace
ax1.xaxis.set_major_locator(ax.xaxis.get_major_locator())
ax1.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: f"{k*x:g}"))
ax1.set_xlabel(f"{k} times quantity $x$")

fig.show()
fig.savefig(fig.get_label() + ".pdf")
```

Hopefully this helps a bit.

Best
Adrien

PS: If there are better solution to share the ticker and the view
limits, I am interesting to know about it :).


Le 25/04/2018 à 05:34, Pierre Haessig a écrit :
Hello,


I'd like to know if it's possible to get a sort of double tick labeling
(e.g. bottom and top), but with different labels. One way to think of my
use case is that there are two different units for the x data (or more
precisely in my case, I've two different x quantities which are bound by
a linear relationship).

The result I'd like is the right part of the attached image (it's a
Gimp-edited mockup composition of the two actual plots on the left).

I've tried to play with the double labeling of a single axe. Indeed, the
following two calls put the double labeling

   ax1.xaxis.set_ticks_position('both')
   ax1.xaxis.set_tick_params(labeltop=True)

However, when I want to alter only the top labels using

   for tick, l in zip(ax1.xaxis.get_major_ticks(), l2):
       tick.set_label2(l)

I get no visible change on the plot. (full script attached). Did I need
to call some update ?

Did I miss something with the proper way to call Tick.set_label2?

Looking at the source code of ax1.xaxis.set_ticklabels, there is
something I don't get. First it sets a FixedFormatter(ticklabels), and
then it sets label1 and/or label2 for each Tick object. So in the end,
where is the text coming from?


Also, to complement the second series of tick labels, I'd like a second
axis label as well. However, I only know
ax.xaxis.set_label_position('top') to move xlabel to the top, not to get
a 2nd one...


As an alternative approach, I see twinx. I didn't try it yet, because I
feel like my objective is not of the objective of twinx (e.g. I'm
plotting only a single dataset, not two). However, I suspect it's
possible to 'bend" twinx to get what I want. What do you think.


Thank you in advance for your ideas.


Best,

Pierre




_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users


<example_pierre.pdf><example_pierre.py>_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users

--
Jody Klymak    






_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: double tick labels (bottom and top, but with different labels)

Pierre Haessig
Thanks for all your feedback. Interesting to see that there are indeed
issues and PR on this topic.

Looking at issue https://github.com/matplotlib/matplotlib/issues/10976,
it's makes no relation to the label2
https://github.com/matplotlib/matplotlib/issues/8181. Seems more like a
"smart twinx", because the ENH propose that the ticks are not
necessarily at the same position.

In my case, since I can use the same xtick positions, I think in the end
I can get away with just using one FuncFormatter which shows the two
numbers. Using Adrien's suggestion, I need to try something like
FuncFormatter(lambda x, pos: f"{x} -- {a*x+b}")).

Best,

Pierre


_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: double tick labels (bottom and top, but with different labels)

vincent.adrien@gmail.com
Hi Pierre,

Related to your last idea, maybe you'll find useful the following formatter:
```python
FuncFormatter(lambda x, pos: f"{x:g}\n{a*x + b:g}")
```
as one can multiline strings as tick labels, to get something as shown
in the attached PDF (the whole script is provided as well). I guess that
one can even do fancier stuff by leveraging the [string formatting
Python
language](https://docs.python.org/3/library/string.html#format-specification-mini-language).

If you find a better way to achieve what you want, please note that
there would be at least one person glad to read about ;).

Best,
Adrien


On 04/26/2018 08:03 AM, Pierre Haessig wrote:

> Thanks for all your feedback. Interesting to see that there are indeed
> issues and PR on this topic.
>
> Looking at issue https://github.com/matplotlib/matplotlib/issues/10976,
> it's makes no relation to the label2
> https://github.com/matplotlib/matplotlib/issues/8181. Seems more like a
> "smart twinx", because the ENH propose that the ticks are not
> necessarily at the same position.
>
> In my case, since I can use the same xtick positions, I think in the end
> I can get away with just using one FuncFormatter which shows the two
> numbers. Using Adrien's suggestion, I need to try something like
> FuncFormatter(lambda x, pos: f"{x} -- {a*x+b}")).
>
> Best,
>
> Pierre
>
>
> _______________________________________________
> Matplotlib-users mailing list
> [hidden email]
> https://mail.python.org/mailman/listinfo/matplotlib-users
>

_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users

example_bis_pierre.py (567 bytes) Download Attachment
example_bis_pierre.pdf (202K) Download Attachment