matplotlib - savefig with usetex = True

时间:2016-04-17 01:59:46

标签: matplotlib postscript axis-labels tex

当我启用plt.plot([1,2,3], [1,2,3], 'b.') plt.text(2,2,r'\textbf{(a)} \lambda_{1} value', usetex=True, fontsize=16, fontname='Times New Roman') plt.savefig('check.eps') 时,我在将matplotlib创建的数字保存为.eps或.ps时遇到问题。如果未启用此功能,则此方法有效。这是一个例子:

File "C:\Python27\lib\site-packages\matplotlib\backends\backend_ps.py", line 671, in draw_tex
thetext = 'psmarker%d' % self.textcnt
AttributeError: 'RendererPS' object has no attribute 'textcnt'

我收到此错误:

usetex=True

启用import pygame import time import random pygame.mixer.pre_init(44100, 16, 2, 4096) pygame.init() boop_sound = pygame.mixer.Sound("boop.wav") display_width = 800 display_height = 600 white = (255,255,255) black = (0,0,0) blue = (0, 0, 150) red = (200,0,0) light_red = (255,0,0) yellow = (200,200,0) light_yellow = (255,255,0) green = (34,177,76) light_green = (0, 255, 0) clock = pygame.time.Clock() smallfont = pygame.font.SysFont("Rockwell", 25) medfont = pygame.font.SysFont("Rockwell", 35) largefont = pygame.font.SysFont("Rockwell", 50) gameDisplay = pygame.display.set_mode((display_width, display_height)) pygame.display.set_caption("How fast can you tap?") ##icon = pygame.image.load("apple.png")#should be 32x32 ##pygame.display.set_icon(icon) pygame.display.update() def score(score): text = smallfont.render("Clicks: "+str(score), True, blue) gameDisplay.blit(text, [2,0]) def game_intro(): intro = True while intro: for event in pygame.event.get(): if event.type== pygame.QUIT: pygame.quit() quit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_c: intro = False if event.key == pygame.K_q: pygame.quit() quit() gameDisplay.fill(white) message_to_screen("How many times can you", blue, -80, "large") message_to_screen("click the button before the time runs out?", blue, -10, "medium") #message_to_screen("Press C to play, P to pause or Q to quit.",black,180) button("Play", 150, 500, 100, 50, green, light_green, action="Play") button("How to play", 325,500,150,50, yellow, light_yellow, action="How to play") button("Quit", 550,500,100,50, red, light_red, action="Quit") pygame.display.update() clock.tick(15) def game_over(): game_over = True while game_over: for event in pygame.event.get(): if event.type== pygame.QUIT: pygame.quit() quit() gameDisplay.fill(white) message_to_screen("Out Of Time!", red, -100, "large") message_to_screen("You clicked: " + str(click) + " times", blue, -30) button("Play Again", 325, 440, 150, 50, green, light_green, action="Play") button("Quit", 350,500,100,50, red, light_red, action="Quit") pygame.display.update() clock.tick(15) def text_objects(text, color, size): if size == "small": textSurface = smallfont.render(text, True, color) elif size == "medium": textSurface = medfont.render(text, True, color) elif size == "large": textSurface = largefont.render(text, True, color) return textSurface, textSurface.get_rect() def text_to_button(msg, color, buttonx, buttony, buttonwidth, buttonheight, size = "small"): textSurf, textRect = text_objects(msg, color, size) textRect.center = ((buttonx +((buttonwidth/2)), buttony+(buttonheight/2))) gameDisplay.blit(textSurf, textRect) def message_to_screen(msg,color, y_displace=0, size = "small"): textSurf, textRect = text_objects(msg, color, size) #screen_text = font.render(msg, True, color) #gameDisplay.blit(screen_text, [display_width/2, display_height/2]) textRect.center = (display_width/ 2), (display_height / 2) + y_displace gameDisplay.blit(textSurf, textRect) def game_controls(): gcont = True while gcont: for event in pygame.event.get(): if event.type== pygame.QUIT: pygame.quit() quit() gameDisplay.fill(white) message_to_screen("How to play", blue, -100,"large") message_to_screen("You have to click the button as many times", black, -40) message_to_screen("as you possible can before the time runs out", black, -20) button("Play", 150, 500, 100, 50, green, light_green, action="Play") button("Main", 350,500,100,50, yellow, light_yellow, action="Main") button("Quit", 550,500,100,50, red, light_red, action="Quit") pygame.display.update() clock.tick(15) def button(text, x, y, width, height, inactive_color, active_color, action = None): cur = pygame.mouse.get_pos() clicked = pygame.mouse.get_pressed() global click if x + width > cur[0] > x and y + height > cur[1] > y: pygame.draw.rect(gameDisplay, active_color, (x, y, width, height)) if clicked[0] == 1 and action != None: if action == "Quit": pygame.quit() quit() if action == "How to play": game_controls() if action == "Play": gameLoop() if action == "Main": game_intro() if action == "Click": click += 1 else: pygame.draw.rect(gameDisplay, inactive_color, (x, y, width, height)) text_to_button(text, black, x, y, width, height) ENDTIMER = pygame.USEREVENT+1 def gameLoop(): gameExit = False gameOver = False FPS = 15 click = 0 global click timed = pygame.time.set_timer(ENDTIMER, 25000) while not gameExit: gameDisplay.fill(white) button("CLICK", display_width/2-100,display_height/2-100, 200,200, red, light_red, action=None) for event in pygame.event.get(): if event.type == pygame.QUIT: gameExit = True if event.type == pygame.MOUSEBUTTONDOWN: pygame.mixer.Sound.play(boop_sound) button("CLICK", display_width/2-100,display_height/2-100, 200,200, red, light_red, action="Click") button("CLICK", display_width/2-100,display_height/2-100, 200,200, red, light_red, action=None) elif event.type == ENDTIMER: game_over() score(click) pygame.display.update() clock.tick(FPS) pygame.quit() quit() game_intro() gameLoop() 时,我也无法使用text命令将字体设置为Time New Roman。

1 个答案:

答案 0 :(得分:0)

即使有些迟,如果有人搜索此错误,我也要给出答案。

保存eps文件将启动RendererPS后端,该后端检查plt.rcParams['text.usetex']是否设置为True来初始化其textcnt属性。由于usetex仅为文本对象设置,因此后端不希望必须处理LaTeX并在尝试时会引发错误。可悲的是,在matplotlib的许多地方都存在与LaTeX渲染有关的这种不一致情况。

如果无法使用标准的matplotib功能实现文本格式设置,则一种解决方案是全局设置usetexplt.rcParams['text.usetex'] = True。这会使用LaTeX渲染图形的所有文本(例如,刻度标签或轴标签)。我建议无论如何都要这样做,以保持一致的视觉效果。

关于字体,fontname参数仅影响标准的matplotlib格式。对于LaTeX渲染,您必须像在LaTeX中一样指定字体。要获得类似Times New Roman的字体,您需要加载相应的程序包,例如mathptmx times(不推荐使用plt.rcParams['text.latex.preamble'] = [r'\usepackage{mathptmx}']包)。当然,该软件包必须安装在本地LaTeX安装中。 matplotlib中的标准字体系列为sans-serif,因此必须使用plt.rcParams['font.family'] = 'serif'更改为serif。

最终代码是:

import matplotlib.pyplot as plt

# LaTeX setup
plt.rcParams['text.latex.preamble'] = [r'\usepackage{mathptmx}']  # load times roman font
plt.rcParams['font.family'] = 'serif'  # use serif font as default
plt.rcParams['text.usetex'] = True  # enable LaTeX rendering globally

plt.plot([1,2,3], [1,2,3], 'b.')
plt.text(2,2,r'\textbf{(a)} $\lambda_1$ value', fontsize=16)
plt.savefig('check.eps')

请注意,必须将数学变量括在美元符号$\lambda_1$中,否则在LaTeX中会出现错误或警告。 (此外,单个字符下标不必放在大括号中。)

作为旁注:在再次关闭usetex后尝试将图形保存为eps时,遇到了相同的错误。