2010-05-09 8 views
14

Voglio generare diagrammi di alta qualità per una presentazione. Sto usando il Matplotlib di Python per generare la grafica. Sfortunatamente, l'esportazione PDF sembra ignorare le mie impostazioni dei caratteri.L'esportazione PDF Matplotlib utilizza font errato

Ho provato a impostare il carattere passando un oggetto FontProperties alle funzioni di disegno del testo e impostando l'opzione globalmente. Per la cronaca, ecco un MWE per riprodurre il problema:

import scipy 
import matplotlib 
matplotlib.use('cairo') 
import matplotlib.pylab as pylab 
import matplotlib.font_manager as fm 

data = scipy.arange(5) 

for font in ['Helvetica', 'Gill Sans']: 
    fig = pylab.figure() 
    ax = fig.add_subplot(111) 
    ax.bar(data, data) 
    ax.set_xticks(data) 
    ax.set_xticklabels(data, fontproperties = fm.FontProperties(family = font)) 
    pylab.savefig('foo-%s.pdf' % font) 

In entrambi i casi, l'output prodotto è identico e usa Helvetica (e sì, lo faccio avere entrambi i font installati).

Giusto per essere sicuri, quanto segue non aiuta:

matplotlib.rc('font', family = 'Gill Sans') 

Infine, se sostituisco il backend, invece di usare il visualizzatore nativo:

matplotlib.use('MacOSX') 

ho fare get viene visualizzato il carattere corretto, ma solo nella GUI del visualizzatore. L'output PDF è ancora una volta sbagliato.

A dire il vero - mi posso impostare altri tipi di carattere - ma solo altre classi di famiglie di font: posso impostare serif font o fantasy o monospace. Ma tutti i font sans-serif sembrano predefiniti a Helvetica.

risposta

3

L'argomento "famiglia" e il parametro rc corrispondente non sono destinati a specificare il nome del font in realtà può essere utilizzato in questo modo. C'è un sistema di selezione dei font (probabilmente barocco) simile a CSS che aiuta lo stesso script a lavorare su computer diversi, selezionando il carattere più vicino disponibile. Il modo generalmente consigliato da usare, ad es. Gill Sans deve aggiungerlo all'inizio del valore del parametro rc font.sans-serif (vedere sample rc file), quindi impostare font.family su sans-serif.

Questo può essere fastidioso se il gestore di font decide per qualche oscuro motivo che Gill Sans non è la corrispondenza più simile alle specifiche. Un modo per aggirare la logica di selezione dei font è utilizzare FontProperties(fname='/path/to/font.ttf') (docstring).

Nel tuo caso, ho il sospetto che il backend MacOSX utilizzi i caratteri tramite i meccanismi del sistema operativo e supporti automaticamente tutti i tipi di font, ma il backend pdf ha il proprio codice di supporto font che non supporta la tua versione di Gill Sans .

+0

Hai detto, "L'argomento" famiglia "[non] ha lo scopo di specificare il nome del carattere" - scusa ma [la documentazione] (http://matplotlib.sourceforge.net/api/font_manager_api.html# matplotlib.font_manager.FontProperties) dice in modo diverso: "Gli elementi ** possono ** includere un nome di famiglia di carattere generico [...]. ** In tal caso **, il carattere effettivo da utilizzare verrà cercato ... "(sottolineatura mia). Inoltre, * funziona * nella GUI. Ad ogni modo, proverò le tue soluzioni proposte. Grazie. –

+1

Usando 'fname = ...' Ricevo un oggetto RuntimeError "Il carattere TrueType manca tabella" nella riga 776 di backend_pdf.py, in 'embedTTFType3' quando si chiama' savefig'. Non sono a casa con TTF e PDF ma ho * già * incorporato Gill Sans nei PDF tramite altri percorsi, quindi non sono sicuro di cosa non ci sia. –

+0

Hai ragione sull'uso di nomi di font reali come argomenti familiari. Il messaggio di errore sembra un bug. Si prega di archiviarlo sul tracker Sourceforge, menzionando il font esatto, la versione matplotlib e il traceback completo. –

8

In sostanza, @ Jouni di è la risposta giusta, ma da quando ho ancora avuto qualche difficoltà a farla funzionare, ecco la mia soluzione finale:

#!/usr/bin/env python2.6 

import scipy 
import matplotlib 
matplotlib.use('cairo') 
import matplotlib.pylab as pylab 
import matplotlib.font_manager as fm 

font = fm.FontProperties(
     family = 'Gill Sans', fname = '/Library/Fonts/GillSans.ttc') 

data = scipy.arange(5) 
fig = pylab.figure() 
ax = fig.add_subplot(111) 
ax.bar(data, data) 
ax.set_yticklabels(ax.get_yticks(), fontproperties = font) 
ax.set_xticklabels(ax.get_xticks(), fontproperties = font) 
pylab.savefig('foo.pdf') 

Si noti che il tipo di carattere deve essere impostato in modo esplicito con il tasto fontproperties. Apparentemente, non c'è l'impostazione rc per la proprietà fname (almeno non l'ho trovata).

Non è necessario fornire una chiave family nell'istanza di font qui, verrà ignorata dal back-end PDF.

Questo codice funziona solo con il backend cairo. L'utilizzo di MacOSX non funzionerà.