Matplotlib navigation toolbar, save image & image text

Good morning,

I have an odd problem with saving plot images via the navigation bar
(unsure if it is unique to the navigation bar) if I have added custom
text.

BACKGROUND.
I have a python gui which is used to connect to some hardware as a
diagnosis tool. Its a pyGTK program and on one ui tab there is an
embeded matplotlib plot.
Now some of the signals I plot rather than being a waveform is more of
a collection of flags (16bit but thats a by and by)
eg:

fault
0 = fault1
0 = fault2
1 = fault3
0 = fault4

so for this I can plot this and it will show 2 (possibly changing w.r.t. time).
I then hook in via a onpick event such that if I click on a plot I
essentially do this:

                    self.figtxt =
self.fig.text(0.79,0.92,'\n'.join(txt),va='top',
bbox=dict(boxstyle='round', facecolor='white',alpha=0.7))
                    self.plot_marker =
self.plot_area.plot(xdata,ydata,'x',color=event.artist.get_color(),ms=7)

ie I put a cross where someone clicked (for indication) and I also
create a texxbox which lists human readable version of what bits are
set.
Great, really helpful in debugging.

The issue is if you click on the save image icon on the navigation
toolbar it saves the waveform and legend BUT not the additional
content (the cross and the textbox).

any idea as to how todo this?

Hi,

I am preparing figures with the following matplotlib preamble:

plt.rc('font', **{'family':'serif', 'serif':['Computer Modern

Roman’],

                  'monospace':['Computer Modern Typewriter']})

params = {'backend': 'ps',

          'text.latex.preamble': [r"\usepackage{upgreek}",

                                  r"\usepackage[nice]{units}"],

          'axes.labelsize': 12,

          'text.fontsize': 12,

          'legend.fontsize': 8,

          'xtick.labelsize': 10,

          'ytick.labelsize': 10,

          'text.usetex': True,

          'figure.figsize': fig_size,

          'axes.unicode_minus': True}

plt.rcParams.update(params)

But when using subscript and superscript in math mode the sizes end

up different than in my LaTeX document (my .cls is using “book” as
base class).

Attached are two screenshots of it rendered from matplotlib and from

Latex (sorry for the different sizes). The “mean” is clearly of
different size in relation to the “d”.

Is there an option to specify a .cls file in rcParams that should be

used for rendering?

I tried:

text.latex.preamble': [r"\documentclass[twoside]{mycls}",

                                  r"\usepackage{upgreek}",

                                  r"\usepackage[nice]{units}"],

but then I get the error:

! LaTeX Error: Two \documentclass or \documentstyle commands.

How to overwrite default matplotlib one? my matplotlibrc has a

commented preamble.

See also my question on tex.stackexchange.com:

http://tex.stackexchange.com/questions/70400/subscript-size-different-in-latex-and-matplotlib

Many thanks

LaTeX_latex_subscript.png

MPL_latex_subscript.png

What you are describing should work as expected. Is it possible that you could make a simple, self-contained version (hopefully it doesn’t need to be embedded to reproduce the problem)? Maybe a modification of one of the existing examples in the online docs might be able to reproduce your issue?

Ben Root

···

On Thu, Sep 6, 2012 at 5:29 AM, Jon Roadley-Battin <jon.roadleybattin@…287…> wrote:

Good morning,

I have an odd problem with saving plot images via the navigation bar

(unsure if it is unique to the navigation bar) if I have added custom

text.

BACKGROUND.

I have a python gui which is used to connect to some hardware as a

diagnosis tool. Its a pyGTK program and on one ui tab there is an

embeded matplotlib plot.

Now some of the signals I plot rather than being a waveform is more of

a collection of flags (16bit but thats a by and by)

eg:

fault

0 = fault1

0 = fault2

1 = fault3

0 = fault4

so for this I can plot this and it will show 2 (possibly changing w.r.t. time).

I then hook in via a onpick event such that if I click on a plot I

essentially do this:

                self.figtxt =

self.fig.text(0.79,0.92,’\n’.join(txt),va=‘top’,

bbox=dict(boxstyle=‘round’, facecolor=‘white’,alpha=0.7))

                self.plot_marker =

self.plot_area.plot(xdata,ydata,‘x’,color=event.artist.get_color(),ms=7)

ie I put a cross where someone clicked (for indication) and I also

create a texxbox which lists human readable version of what bits are

set.

Great, really helpful in debugging.

The issue is if you click on the save image icon on the navigation

toolbar it saves the waveform and legend BUT not the additional

content (the cross and the textbox).

any idea as to how todo this?

This might have been fixed at one point. Which version of matplotlib are you using?

Ben Root

···

On Thu, Sep 6, 2012 at 6:54 AM, Mogliii <mogliii@…361…> wrote:

Hi,

I am preparing figures with the following matplotlib preamble:



plt.rc('font', **{'family':'serif', 'serif':['Computer Modern

Roman’],

                  'monospace':['Computer Modern Typewriter']})

params = {'backend': 'ps',

          'text.latex.preamble': [r"\usepackage{upgreek}",

                                  r"\usepackage[nice]{units}"],

          'axes.labelsize': 12,

          'text.fontsize': 12,

          'legend.fontsize': 8,

          'xtick.labelsize': 10,

          'ytick.labelsize': 10,

          'text.usetex': True,

          'figure.figsize': fig_size,

          'axes.unicode_minus': True}

plt.rcParams.update(params)





But when using subscript and superscript in math mode the sizes end

up different than in my LaTeX document (my .cls is using “book” as
base class).

Attached are two screenshots of it rendered from matplotlib and from

Latex (sorry for the different sizes). The “mean” is clearly of
different size in relation to the “d”.

Is there an option to specify a .cls file in rcParams that should be

used for rendering?

I tried:

text.latex.preamble': [r"\documentclass[twoside]{mycls}",

                                  r"\usepackage{upgreek}",

                                  r"\usepackage[nice]{units}"],

but then I get the error:

! LaTeX Error: Two \documentclass or \documentstyle commands.



How to overwrite default matplotlib one? my matplotlibrc has a

commented preamble.

See also my question on [tex.stackexchange.com](http://tex.stackexchange.com)
:

http://tex.stackexchange.com/questions/70400/subscript-size-different-in-latex-and-matplotlib

Many thanks

Good afternoon,
I agree it should work and the examples i have run allow this so this
is why I am looking over my specifics.
The only thing I can see is the examples call to add txt via an axes
entity, I have been doing it via a figure entity.

I am going to re-write to draw on the axis (last time I did this it
didn't display hence going for a figure).

If this doesn't work I shall strip the code down to a minimum example
demonstrating what I am describing

···

On 6 September 2012 14:20, Benjamin Root <ben.root@...1304...> wrote:

On Thu, Sep 6, 2012 at 5:29 AM, Jon Roadley-Battin > <jon.roadleybattin@...287...> wrote:

Good morning,

I have an odd problem with saving plot images via the navigation bar
(unsure if it is unique to the navigation bar) if I have added custom
text.

BACKGROUND.
I have a python gui which is used to connect to some hardware as a
diagnosis tool. Its a pyGTK program and on one ui tab there is an
embeded matplotlib plot.
Now some of the signals I plot rather than being a waveform is more of
a collection of flags (16bit but thats a by and by)
eg:

fault
0 = fault1
0 = fault2
1 = fault3
0 = fault4

so for this I can plot this and it will show 2 (possibly changing w.r.t.
time).
I then hook in via a onpick event such that if I click on a plot I
essentially do this:

                    self.figtxt =
self.fig.text(0.79,0.92,'\n'.join(txt),va='top',
bbox=dict(boxstyle='round', facecolor='white',alpha=0.7))
                    self.plot_marker =
self.plot_area.plot(xdata,ydata,'x',color=event.artist.get_color(),ms=7)

ie I put a cross where someone clicked (for indication) and I also
create a texxbox which lists human readable version of what bits are
set.
Great, really helpful in debugging.

The issue is if you click on the save image icon on the navigation
toolbar it saves the waveform and legend BUT not the additional
content (the cross and the textbox).

any idea as to how todo this?

What you are describing should work as expected. Is it possible that you
could make a simple, self-contained version (hopefully it doesn't need to be
embedded to reproduce the problem)? Maybe a modification of one of the
existing examples in the online docs might be able to reproduce your issue?

Ben Root

I found the solution. My LaTeX file uses the package amsmath, which
also loads amstext. And that is invoked when using \text{} or
\textnormal{} inside a formula.
So the solution in matplotlib is to add the following to the
preamble:
‘text.latex.preamble’: [r"\usepackage{upgreek}",
r"\usepackage[nice]{units}",
],
I was using matplotlib 1.1, now updated to 1.1.1, but that did not
affect it. Also, I am not using the built-in LaTeX typesetting.

···

On 06/09/2012 14:49, Benjamin Root
wrote:

On Thu, Sep 6, 2012 at 6:54 AM, Mogliii <mogliii@…361…>
wrote:

Hi,

        I am preparing figures with the following matplotlib

preamble:

        plt.rc('font', **{'family':'serif', 'serif':['Computer

Modern Roman’],

                          'monospace':['Computer Modern

Typewriter’]})

        params = {'backend': 'ps',

                  'text.latex.preamble': [r"\usepackage{upgreek}",

r"\usepackage[nice]{units}"],

                  'axes.labelsize': 12,

                  'text.fontsize': 12,

                  'legend.fontsize': 8,

                  'xtick.labelsize': 10,

                  'ytick.labelsize': 10,

                  'text.usetex': True,

                  'figure.figsize': fig_size,

                  'axes.unicode_minus': True}

        plt.rcParams.update(params)





        But when using subscript and superscript in math mode the

sizes end up different than in my LaTeX document (my .cls is
using “book” as base class).

        Attached are two screenshots of it rendered from matplotlib

and from Latex (sorry for the different sizes). The “mean”
is clearly of different size in relation to the “d”.

        Is there an option to specify a .cls file in rcParams that

should be used for rendering?

        I tried:

        text.latex.preamble': [r"\documentclass[twoside]{mycls}",

                                          r"\usepackage{upgreek}",

r"\usepackage[nice]{units}"],

        but then I get the error:

        ! LaTeX Error: Two \documentclass or \documentstyle

commands.

        How to overwrite default matplotlib one? my matplotlibrc has

a commented preamble.

        See also my question on [tex.stackexchange.com](http://tex.stackexchange.com)            :

http://tex.stackexchange.com/questions/70400/subscript-size-different-in-latex-and-matplotlib

        Many thanks
      This might have been fixed at one point.  Which version of

matplotlib are you using?

      Ben Root

r"\usepackage{amstext}"

Well I have narrowed down exactly what causes it and produced a
stripped down piece of code that reproduces the effect.

It is related to events. I use mpl_connect to connect two functions
#1 onpick - when a plot is picked annotate plot (in practice IF it is
a binary array then annotate)
#2 onpress - click anywhere else and it clears said annotation.

Works well (probably not the best way todo this, but it works). Thing
is it seems my onpress method is called when I click on the save on
the toolbar

I guess I should add an if statement ( if event.inaxis ...) so that
the remove method isn't called outside of the axes area

#!/usr/bin/env python
from matplotlib.pyplot import figure, show
import numpy as np
fig = figure()
text = None

x = np.arange(0,10,0.2)
y = np.arange(10,20,0.2)

ax = fig.add_subplot(111)
ax.plot(x,y,picker=5)

def onpick(event):
    global text
    x = event.artist.get_xdata()[event.ind][0]
    y = event.artist.get_ydata()[event.ind][0]
    text = ax.annotate('foo',xy=(x,y),xytext=(0.8,
0.9),textcoords='axes fraction')
    fig.canvas.draw()

def onpress(event):
    global text
    try:
  text.remove()
    except:
        fig.canvas.draw()

fig.canvas.mpl_connect('button_press_event', onpress)
fig.canvas.mpl_connect('pick_event', onpick)
show()

···

On 6 September 2012 14:55, Jon Roadley-Battin <jon.roadleybattin@...287...> wrote:

On 6 September 2012 14:20, Benjamin Root <ben.root@...1304...> wrote:

On Thu, Sep 6, 2012 at 5:29 AM, Jon Roadley-Battin >> <jon.roadleybattin@...287...> wrote:

Good morning,

I have an odd problem with saving plot images via the navigation bar
(unsure if it is unique to the navigation bar) if I have added custom
text.

BACKGROUND.
I have a python gui which is used to connect to some hardware as a
diagnosis tool. Its a pyGTK program and on one ui tab there is an
embeded matplotlib plot.
Now some of the signals I plot rather than being a waveform is more of
a collection of flags (16bit but thats a by and by)
eg:

fault
0 = fault1
0 = fault2
1 = fault3
0 = fault4

so for this I can plot this and it will show 2 (possibly changing w.r.t.
time).
I then hook in via a onpick event such that if I click on a plot I
essentially do this:

                    self.figtxt =
self.fig.text(0.79,0.92,'\n'.join(txt),va='top',
bbox=dict(boxstyle='round', facecolor='white',alpha=0.7))
                    self.plot_marker =
self.plot_area.plot(xdata,ydata,'x',color=event.artist.get_color(),ms=7)

ie I put a cross where someone clicked (for indication) and I also
create a texxbox which lists human readable version of what bits are
set.
Great, really helpful in debugging.

The issue is if you click on the save image icon on the navigation
toolbar it saves the waveform and legend BUT not the additional
content (the cross and the textbox).

any idea as to how todo this?

What you are describing should work as expected. Is it possible that you
could make a simple, self-contained version (hopefully it doesn't need to be
embedded to reproduce the problem)? Maybe a modification of one of the
existing examples in the online docs might be able to reproduce your issue?

Ben Root

Good afternoon,
I agree it should work and the examples i have run allow this so this
is why I am looking over my specifics.
The only thing I can see is the examples call to add txt via an axes
entity, I have been doing it via a figure entity.

I am going to re-write to draw on the axis (last time I did this it
didn't display hence going for a figure).

If this doesn't work I shall strip the code down to a minimum example
demonstrating what I am describing

Yup, that would do it. Because of how you structured your try/except statement in onpress(), the canvas is only re-drawn upon any unsuccessful attempts of removing the text. So, after you save, you still see the text objects there because the canvas hasn’t been redrawn. Doing a test for “event.inaxes” is the correct way to go there (and making sure you do the draw at the right situation).

Cheers!
Ben Root

···

On Thu, Sep 6, 2012 at 4:37 PM, Jon Roadley-Battin <jon.roadleybattin@…287…> wrote:

On 6 September 2012 14:55, Jon Roadley-Battin > <jon.roadleybattin@…287…> wrote:

On 6 September 2012 14:20, Benjamin Root <ben.root@…1304…> wrote:

On Thu, Sep 6, 2012 at 5:29 AM, Jon Roadley-Battin > > >> <jon.roadleybattin@…287…> wrote:

Good morning,

I have an odd problem with saving plot images via the navigation bar

(unsure if it is unique to the navigation bar) if I have added custom

text.

BACKGROUND.

I have a python gui which is used to connect to some hardware as a

diagnosis tool. Its a pyGTK program and on one ui tab there is an

embeded matplotlib plot.

Now some of the signals I plot rather than being a waveform is more of

a collection of flags (16bit but thats a by and by)

eg:

fault

0 = fault1

0 = fault2

1 = fault3

0 = fault4

so for this I can plot this and it will show 2 (possibly changing w.r.t.

time).

I then hook in via a onpick event such that if I click on a plot I

essentially do this:

                self.figtxt =

self.fig.text(0.79,0.92,’\n’.join(txt),va=‘top’,

bbox=dict(boxstyle=‘round’, facecolor=‘white’,alpha=0.7))

                self.plot_marker =

self.plot_area.plot(xdata,ydata,‘x’,color=event.artist.get_color(),ms=7)

ie I put a cross where someone clicked (for indication) and I also

create a texxbox which lists human readable version of what bits are

set.

Great, really helpful in debugging.

The issue is if you click on the save image icon on the navigation

toolbar it saves the waveform and legend BUT not the additional

content (the cross and the textbox).

any idea as to how todo this?

What you are describing should work as expected. Is it possible that you

could make a simple, self-contained version (hopefully it doesn’t need to be

embedded to reproduce the problem)? Maybe a modification of one of the

existing examples in the online docs might be able to reproduce your issue?

Ben Root

Good afternoon,

I agree it should work and the examples i have run allow this so this

is why I am looking over my specifics.

The only thing I can see is the examples call to add txt via an axes

entity, I have been doing it via a figure entity.

I am going to re-write to draw on the axis (last time I did this it

didn’t display hence going for a figure).

If this doesn’t work I shall strip the code down to a minimum example

demonstrating what I am describing

Well I have narrowed down exactly what causes it and produced a

stripped down piece of code that reproduces the effect.

It is related to events. I use mpl_connect to connect two functions

#1 onpick - when a plot is picked annotate plot (in practice IF it is

a binary array then annotate)

#2 onpress - click anywhere else and it clears said annotation.

Works well (probably not the best way todo this, but it works). Thing

is it seems my onpress method is called when I click on the save on

the toolbar

I guess I should add an if statement ( if event.inaxis …) so that

the remove method isn’t called outside of the axes area

Thats the plan.
The problem is clicking on a plot calls both onpick and onpress (hence
the additional fig.canvas.draw() to work around this).

ill put a flag in and do an if/else on that as well