Type 1 fonts with log graphs

Hi,

I'm trying to use Matplotlib graphs as part of a camera-ready
submission, and the publishing house requires the use of Type 1 fonts
only.

I'm finding that the PDF backend happily outputs Type-1 fonts for
simple graphs with linear Y axes, but outputs Type-3 fonts for
logarithmic Y axes.

Using a logarithmic yscale incurs the use of mathtext, which seems to
use Type 3 fonts, presumably because of the default use of exponential
notation. I can use an ugly hack to get around this - using
pyplot.yticks() to force the axis ticks to not use exponents - but
this would require moving the plot region to accommodate large labels
(like 10 ^ 6) or writing the axes as 10, 100, 1K, etc. so they fit.

There's a minimum working example below, which I've tested with the
matplotlib master branch as of today, as well as 1.1.1, which produces
the same behavior, so I don't know that this is a bug, probably just
unexpected behavior.

#!/usr/bin/env python
# Simple program to test for type 1 fonts.
# Generate a line graph w/linear and log Y axes.

from matplotlib import rc, rcParams

#rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})

# These lines are needed to get type-1 results:
# http://nerdjusttyped.blogspot.com/2010/07/type-1-fonts-and-matplotlib-figures.html
rcParams['ps.useafm'] = True
rcParams['pdf.use14corefonts'] = True
rcParams['text.usetex'] = False

import matplotlib.pyplot as plt

YSCALES = ['linear', 'log']

def plot(filename, yscale):
    plt.figure(1)
    xvals = range(1, 2)
    yvals = xvals
    plt.plot(xvals, yvals)
    plt.yscale(yscale)
    #YTICKS = [1, 10]
    #plt.yticks(YTICKS, YTICKS) # locs, labels
    ax = plt.gca()
    #print ax.get_xticklabels()[0].get_text()
    print ",".join([a.get_label() for a in ax.get_yticklabels()])
    plt.savefig(filename + '.pdf')

if __name__ == '__main__':
    for yscale in YSCALES:
        plot('linegraph-' + yscale, yscale)

Does anyone know a clean way to get Type 1 fonts with log axes?

Thanks,
Brandon

Hi Brandon,

I notice that this is cross-posted on StackOverflow (http://stackoverflow.com/questions/13132194/type-1-fonts-with-log-graphs).
Personally, I have no problem with cross posting, but to save two people having to answer the same question, I would make sure it was explicit that this had also been posted elsewhere.

Thanks,

Phil

···

On 30 October 2012 03:13, Brandon Heller <brandonh@…200…> wrote:

Hi,

I’m trying to use Matplotlib graphs as part of a camera-ready

submission, and the publishing house requires the use of Type 1 fonts

only.

I’m finding that the PDF backend happily outputs Type-1 fonts for

simple graphs with linear Y axes, but outputs Type-3 fonts for

logarithmic Y axes.

Using a logarithmic yscale incurs the use of mathtext, which seems to

use Type 3 fonts, presumably because of the default use of exponential

notation. I can use an ugly hack to get around this - using

pyplot.yticks() to force the axis ticks to not use exponents - but

this would require moving the plot region to accommodate large labels

(like 10 ^ 6) or writing the axes as 10, 100, 1K, etc. so they fit.

There’s a minimum working example below, which I’ve tested with the

matplotlib master branch as of today, as well as 1.1.1, which produces

the same behavior, so I don’t know that this is a bug, probably just

unexpected behavior.

#!/usr/bin/env python

Simple program to test for type 1 fonts.

Generate a line graph w/linear and log Y axes.

from matplotlib import rc, rcParams

#rc(‘font’,**{‘family’:‘sans-serif’,‘sans-serif’:[‘Helvetica’]})

These lines are needed to get type-1 results:

http://nerdjusttyped.blogspot.com/2010/07/type-1-fonts-and-matplotlib-figures.html

rcParams[‘ps.useafm’] = True

rcParams[‘pdf.use14corefonts’] = True

rcParams[‘text.usetex’] = False

import matplotlib.pyplot as plt

YSCALES = [‘linear’, ‘log’]

def plot(filename, yscale):

plt.figure(1)

xvals = range(1, 2)

yvals = xvals

plt.plot(xvals, yvals)

plt.yscale(yscale)

#YTICKS = [1, 10]

#plt.yticks(YTICKS, YTICKS)  # locs, labels

ax = plt.gca()

#print ax.get_xticklabels()[0].get_text()

print ",".join([a.get_label() for a in ax.get_yticklabels()])

plt.savefig(filename + '.pdf')

if name == ‘main’:

for yscale in YSCALES:

    plot('linegraph-' + yscale, yscale)

Does anyone know a clean way to get Type 1 fonts with log axes?

Thanks,

Brandon


Everyone hates slow websites. So do we.

Make your web apps faster with AppDynamics

Download AppDynamics Lite for free today:

http://p.sf.net/sfu/appdyn_sfd2d_oct


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

There are a couple of alternative formatters for log scaling that don't require mathtext.

You can do:

from matplotlib.tickers import LogFormatter, LogFormatterExponent
...
ax.xaxis.set_major_formatter(LogFormatter())
# or LogFormatterExponent(), which is just the exponent

To clarify the font issue. The PDF backend has no support for outputting Type 1 fonts. There is an rcParam "pdf.fonttype" that allows you to choose between Type 3 and Type 42 fonts, however. Type 3 stores each character as a path and then uses those to put strings together. It supports font subsetting, so an entire large font is not embedded in the file. Type 42 (essentially) just embeds a TrueType font in the file, and we don't support subsetting there.

There is also the "pdf.use14corefonts" that will use the 14 built-in PDF fonts whenever possible (and therefore not embed any fonts). However, mathtext requires a special font for the math symbols, and thus it starts to embed fonts.

You may try setting "mathtext.default" to "regular", which will use the font used as the default for the rest of the text first. This should have the effect of not embedding any extra fonts in the file as long as you don't use any special symbols in the math.

Mike

···

On 10/30/2012 05:23 AM, Phil Elson wrote:

Hi Brandon,

I notice that this is cross-posted on StackOverflow (python - Type 1 fonts with log graphs - Stack Overflow).
Personally, I have no problem with cross posting, but to save two people having to answer the same question, I would make sure it was explicit that this had also been posted elsewhere.

Thanks,

Phil

On 30 October 2012 03:13, Brandon Heller <brandonh@...200... > <mailto:brandonh@…200…>> wrote:

    Hi,

    I'm trying to use Matplotlib graphs as part of a camera-ready
    submission, and the publishing house requires the use of Type 1 fonts
    only.

    I'm finding that the PDF backend happily outputs Type-1 fonts for
    simple graphs with linear Y axes, but outputs Type-3 fonts for
    logarithmic Y axes.

    Using a logarithmic yscale incurs the use of mathtext, which seems to
    use Type 3 fonts, presumably because of the default use of exponential
    notation. I can use an ugly hack to get around this - using
    pyplot.yticks() to force the axis ticks to not use exponents - but
    this would require moving the plot region to accommodate large labels
    (like 10 ^ 6) or writing the axes as 10, 100, 1K, etc. so they fit.

    There's a minimum working example below, which I've tested with the
    matplotlib master branch as of today, as well as 1.1.1, which produces
    the same behavior, so I don't know that this is a bug, probably just
    unexpected behavior.

    #!/usr/bin/env python
    # Simple program to test for type 1 fonts.
    # Generate a line graph w/linear and log Y axes.

    from matplotlib import rc, rcParams

    #rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})

    # These lines are needed to get type-1 results:
    #
    Top 5 tips: Type 1 Fonts and matplotlib figures
    rcParams['ps.useafm'] = True
    rcParams['pdf.use14corefonts'] = True
    rcParams['text.usetex'] = False

    import matplotlib.pyplot as plt

    YSCALES = ['linear', 'log']

    def plot(filename, yscale):
        plt.figure(1)
        xvals = range(1, 2)
        yvals = xvals
        plt.plot(xvals, yvals)
        plt.yscale(yscale)
        #YTICKS = [1, 10]
        #plt.yticks(YTICKS, YTICKS) # locs, labels
        ax = plt.gca()
        #print ax.get_xticklabels()[0].get_text()
        print ",".join([a.get_label() for a in ax.get_yticklabels()])
        plt.savefig(filename + '.pdf')

    if __name__ == '__main__':
        for yscale in YSCALES:
            plot('linegraph-' + yscale, yscale)

    Does anyone know a clean way to get Type 1 fonts with log axes?

    Thanks,
    Brandon

    ------------------------------------------------------------------------------
    Everyone hates slow websites. So do we.
    Make your web apps faster with AppDynamics
    Download AppDynamics Lite for free today:
    http://p.sf.net/sfu/appdyn_sfd2d_oct
    _______________________________________________
    Matplotlib-users mailing list
    Matplotlib-users@lists.sourceforge.net
    <mailto:Matplotlib-users@lists.sourceforge.net>
    matplotlib-users List Signup and Options

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_sfd2d_oct

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
matplotlib-users List Signup and Options

Hi Phil,

Next time I’ll be more explicit. I added the question to SA after I tried to get a public link to my message and saw that archives past July of this year seem to be missing. It wasn’t clear that this list was even still alive:

http://sourceforge.net/mailarchive/forum.php?forum_name=matplotlib-users

Any idea why the archives seem to have stopped?

Thanks,

Brandon

···

On Tue, Oct 30, 2012 at 2:23 AM, Phil Elson <pelson.pub@…287…> wrote:

Hi Brandon,

I notice that this is cross-posted on StackOverflow (http://stackoverflow.com/questions/13132194/type-1-fonts-with-log-graphs).

Personally, I have no problem with cross posting, but to save two people having to answer the same question, I would make sure it was explicit that this had also been posted elsewhere.

Thanks,

Phil

On 30 October 2012 03:13, Brandon Heller <brandonh@…200…> wrote:

Hi,

I’m trying to use Matplotlib graphs as part of a camera-ready

submission, and the publishing house requires the use of Type 1 fonts

only.

I’m finding that the PDF backend happily outputs Type-1 fonts for

simple graphs with linear Y axes, but outputs Type-3 fonts for

logarithmic Y axes.

Using a logarithmic yscale incurs the use of mathtext, which seems to

use Type 3 fonts, presumably because of the default use of exponential

notation. I can use an ugly hack to get around this - using

pyplot.yticks() to force the axis ticks to not use exponents - but

this would require moving the plot region to accommodate large labels

(like 10 ^ 6) or writing the axes as 10, 100, 1K, etc. so they fit.

There’s a minimum working example below, which I’ve tested with the

matplotlib master branch as of today, as well as 1.1.1, which produces

the same behavior, so I don’t know that this is a bug, probably just

unexpected behavior.

#!/usr/bin/env python

Simple program to test for type 1 fonts.

Generate a line graph w/linear and log Y axes.

from matplotlib import rc, rcParams

#rc(‘font’,**{‘family’:‘sans-serif’,‘sans-serif’:[‘Helvetica’]})

These lines are needed to get type-1 results:

http://nerdjusttyped.blogspot.com/2010/07/type-1-fonts-and-matplotlib-figures.html

rcParams[‘ps.useafm’] = True

rcParams[‘pdf.use14corefonts’] = True

rcParams[‘text.usetex’] = False

import matplotlib.pyplot as plt

YSCALES = [‘linear’, ‘log’]

def plot(filename, yscale):

plt.figure(1)

xvals = range(1, 2)

yvals = xvals

plt.plot(xvals, yvals)

plt.yscale(yscale)

#YTICKS = [1, 10]

#plt.yticks(YTICKS, YTICKS)  # locs, labels

ax = plt.gca()

#print ax.get_xticklabels()[0].get_text()

print ",".join([a.get_label() for a in ax.get_yticklabels()])

plt.savefig(filename + '.pdf')

if name == ‘main’:

for yscale in YSCALES:

    plot('linegraph-' + yscale, yscale)

Does anyone know a clean way to get Type 1 fonts with log axes?

Thanks,

Brandon


Everyone hates slow websites. So do we.

Make your web apps faster with AppDynamics

Download AppDynamics Lite for free today:

http://p.sf.net/sfu/appdyn_sfd2d_oct


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

  There are a couple of alternative

formatters for log scaling that don’t require mathtext.

  You can do:



  from matplotlib.tickers import LogFormatter, LogFormatterExponent

  ...

  ax.xaxis.set_major_formatter(LogFormatter()) 

  # or LogFormatterExponent(), which is just the exponent
  To clarify the font issue.  The PDF backend has no support for

outputting Type 1 fonts. There is an rcParam “pdf.fonttype” that
allows you to choose between Type 3 and Type 42 fonts, however.
Type 3 stores each character as a path and then uses those to put
strings together. It supports font subsetting, so an entire large
font is not embedded in the file. Type 42 (essentially) just
embeds a TrueType font in the file, and we don’t support
subsetting there.

  There is also the "pdf.use14corefonts" that will use the 14

built-in PDF fonts whenever possible (and therefore not embed any
fonts). However, mathtext requires a special font for the math
symbols, and thus it starts to embed fonts.

  You may try setting "mathtext.default" to "regular", which will

use the font used as the default for the rest of the text first.
This should have the effect of not embedding any extra fonts in
the file as long as you don’t use any special symbols in the math.

Hi Mike,

Thanks for the suggestions - I tried both. The first (use a LogFormatter) yields only Type 1 but doesn’t look look as good as exponential notation (my style preference). The second (mathtext.default = regular) defaulted to CMR and kept the exponents as Type 1, but not the helvetica used by the rest of the graph. It used CMR even when I had set another font as the default:

rc(‘font’,**{‘family’:‘sans-serif’,‘sans-serif’:[‘Helvetica’]})

… so maybe I’m not setting the default properly. Any ideas there?

A suggestion from my colleague Vimal Kumar was to post-process the output to replace Type3 w/Type 1:

sed -i.bak \

-e “s/Type3/Type1/g” \

-e “s/BitstreamVeraSans-Roman/Helvetica/g” \

-e “s/DejaVuSans/Helvetica/g” \

$file

This has the advantage that no mattext or tex is required, though I have to assume the letter spacing is meant for the original font. In practice, the only replaced fonts are on the Y axis, so even if the spacing between letters seems a bit bigger, I don’t think this is a huge issue. Of course, it would still be nice to solve this problem in MPL itself, though.

Thanks,

Brandon

···

On Tue, Oct 30, 2012 at 5:51 AM, Michael Droettboom <mdroe@…86…> wrote:

  Mike
  On 10/30/2012 05:23 AM, Phil Elson wrote:

Hi Brandon,

  I notice that this is cross-posted on StackOverflow ([http://stackoverflow.com/questions/13132194/type-1-fonts-with-log-graphs](http://stackoverflow.com/questions/13132194/type-1-fonts-with-log-graphs)).



  Personally, I have no problem with cross posting, but to save two

people having to answer the same question, I would make sure it
was explicit that this had also been posted elsewhere.

  Thanks,



  Phil




    On 30 October 2012 03:13, Brandon Heller > > <brandonh@...200...> > >         wrote:

Hi,

      I'm trying to use Matplotlib graphs as part of a camera-ready

      submission, and the publishing house requires the use of Type

1 fonts

      only.



      I'm finding that the PDF backend happily outputs Type-1 fonts

for

      simple graphs with linear Y axes, but outputs Type-3 fonts for

      logarithmic Y axes.



      Using a logarithmic yscale incurs the use of mathtext, which

seems to

      use Type 3 fonts, presumably because of the default use of

exponential

      notation.  I can use an ugly hack to get around this - using

      pyplot.yticks() to force the axis ticks to not use exponents -

but

      this would require moving the plot region to accommodate large

labels

      (like 10 ^ 6) or writing the axes as 10, 100, 1K, etc. so they

fit.

      There's a minimum working example below, which I've tested

with the

      matplotlib master branch as of today, as well as 1.1.1, which

produces

      the same behavior, so I don't know that this is a bug,

probably just

      unexpected behavior.





      #!/usr/bin/env python

      # Simple program to test for type 1 fonts.

      # Generate a line graph w/linear and log Y axes.



      from matplotlib import rc, rcParams

#rc(‘font’,**{‘family’:‘sans-serif’,‘sans-serif’:[‘Helvetica’]})

      # These lines are needed to get type-1 results:

      # [http://nerdjusttyped.blogspot.com/2010/07/type-1-fonts-and-matplotlib-figures.html](http://nerdjusttyped.blogspot.com/2010/07/type-1-fonts-and-matplotlib-figures.html)

      rcParams['ps.useafm'] = True

      rcParams['pdf.use14corefonts'] = True

      rcParams['text.usetex'] = False



      import matplotlib.pyplot as plt



      YSCALES = ['linear', 'log']



      def plot(filename, yscale):

          plt.figure(1)

          xvals = range(1, 2)

          yvals = xvals

          plt.plot(xvals, yvals)

          plt.yscale(yscale)

          #YTICKS = [1, 10]

          #plt.yticks(YTICKS, YTICKS)  # locs, labels

          ax = plt.gca()

          #print ax.get_xticklabels()[0].get_text()

          print ",".join([a.get_label() for a in

ax.get_yticklabels()])

          plt.savefig(filename + '.pdf')





      if __name__ == '__main__':

          for yscale in YSCALES:

              plot('linegraph-' + yscale, yscale)







      Does anyone know a clean way to get Type 1 fonts with log

axes?

      Thanks,

      Brandon

      Everyone hates slow websites. So do we.

      Make your web apps faster with AppDynamics

      Download AppDynamics Lite for free today:

      [http://p.sf.net/sfu/appdyn_sfd2d_oct](http://p.sf.net/sfu/appdyn_sfd2d_oct)

      _______________________________________________

      Matplotlib-users mailing list

      Matplotlib-users@lists.sourceforge.net

      [https://lists.sourceforge.net/lists/listinfo/matplotlib-users](https://lists.sourceforge.net/lists/listinfo/matplotlib-users)
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
[http://p.sf.net/sfu/appdyn_sfd2d_oct](http://p.sf.net/sfu/appdyn_sfd2d_oct)
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
[https://lists.sourceforge.net/lists/listinfo/matplotlib-users](https://lists.sourceforge.net/lists/listinfo/matplotlib-users)

Everyone hates slow websites. So do we.

Make your web apps faster with AppDynamics

Download AppDynamics Lite for free today:

http://p.sf.net/sfu/appdyn_sfd2d_oct


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Thanks for pointing that out. I’m not sure what’s wrong, but I’ll
look into it.
Mike

···

On 10/30/2012 12:25 PM, Brandon Heller
wrote:

Hi Phil,

    Next time I'll be more explicit.  I added the question to SA

after I tried to get a public link to my message and saw that
archives past July of this year seem to be missing. It wasn’t
clear that this list was even still alive:

http://sourceforge.net/mailarchive/forum.php?forum_name=matplotlib-users

Any idea why the archives seem to have stopped?

Thanks,

Brandon

      On Tue, Oct 30, 2012 at 2:23 AM, Phil

Elson <pelson.pub@…287…>
wrote:

        Hi

Brandon,

        I notice that this is cross-posted on StackOverflow ([http://stackoverflow.com/questions/13132194/type-1-fonts-with-log-graphs](http://stackoverflow.com/questions/13132194/type-1-fonts-with-log-graphs)).

        Personally, I have no problem with cross posting, but to

save two people having to answer the same question, I would
make sure it was explicit that this had also been posted
elsewhere.

        Thanks,



        Phil




              On 30 October 2012 03:13, Brandon Heller

<brandonh@…200…>
wrote:

Hi,

                I'm trying to use Matplotlib graphs as part of a

camera-ready

                submission, and the publishing house requires the

use of Type 1 fonts

                only.



                I'm finding that the PDF backend happily outputs

Type-1 fonts for

                simple graphs with linear Y axes, but outputs Type-3

fonts for

                logarithmic Y axes.



                Using a logarithmic yscale incurs the use of

mathtext, which seems to

                use Type 3 fonts, presumably because of the default

use of exponential

                notation.  I can use an ugly hack to get around this
  • using

                  pyplot.yticks() to force the axis ticks to not use
    

exponents - but

                this would require moving the plot region to

accommodate large labels

                (like 10 ^ 6) or writing the axes as 10, 100, 1K,

etc. so they fit.

                There's a minimum working example below, which I've

tested with the

                matplotlib master branch as of today, as well as

1.1.1, which produces

                the same behavior, so I don't know that this is a

bug, probably just

                unexpected behavior.





                #!/usr/bin/env python

                # Simple program to test for type 1 fonts.

                # Generate a line graph w/linear and log Y axes.



                from matplotlib import rc, rcParams

#rc(‘font’,**{‘family’:‘sans-serif’,‘sans-serif’:[‘Helvetica’]})

                # These lines are needed to get type-1 results:

                # [http://nerdjusttyped.blogspot.com/2010/07/type-1-fonts-and-matplotlib-figures.html](http://nerdjusttyped.blogspot.com/2010/07/type-1-fonts-and-matplotlib-figures.html)

                rcParams['ps.useafm'] = True

                rcParams['pdf.use14corefonts'] = True

                rcParams['text.usetex'] = False



                import matplotlib.pyplot as plt



                YSCALES = ['linear', 'log']



                def plot(filename, yscale):

                    plt.figure(1)

                    xvals = range(1, 2)

                    yvals = xvals

                    plt.plot(xvals, yvals)

                    plt.yscale(yscale)

                    #YTICKS = [1, 10]

                    #plt.yticks(YTICKS, YTICKS)  # locs, labels

                    ax = plt.gca()

                    #print ax.get_xticklabels()[0].get_text()

                    print ",".join([a.get_label() for a in

ax.get_yticklabels()])

                    plt.savefig(filename + '.pdf')





                if __name__ == '__main__':

                    for yscale in YSCALES:

                        plot('linegraph-' + yscale, yscale)







                Does anyone know a clean way to get Type 1 fonts

with log axes?

                Thanks,

                Brandon

            Everyone hates slow websites. So do we.

            Make your web apps faster with AppDynamics

            Download AppDynamics Lite for free today:

            [http://p.sf.net/sfu/appdyn_sfd2d_oct](http://p.sf.net/sfu/appdyn_sfd2d_oct)

            _______________________________________________

            Matplotlib-users mailing list

            Matplotlib-users@lists.sourceforge.net

            [https://lists.sourceforge.net/lists/listinfo/matplotlib-users](https://lists.sourceforge.net/lists/listinfo/matplotlib-users)
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
_______________________________________________
Matplotlib-users mailing list

http://p.sf.net/sfu/appdyn_sfd2d_octMatplotlib-users@lists.sourceforge.nethttps://lists.sourceforge.net/lists/listinfo/matplotlib-users