savefig plots how guardar python performance matplotlib plot cstring

plots - savefig en python



Matplotlib, alternativas a savefig() para mejorar el rendimiento al guardar en un objeto CString? (2)

Estoy tratando de acelerar el proceso de guardar mis cuadros en imágenes. En este momento estoy creando un objeto cString donde guardo el gráfico usando savefig; pero realmente agradecería cualquier ayuda para mejorar este método de guardar la imagen. Tengo que hacer esta operación docenas de veces, y el comando savefig es muy lento; debe haber una mejor manera de hacerlo. Leí algo sobre guardarlo como una imagen sin comprimir, pero no tengo ni idea de cómo hacerlo. Realmente no me importa mucho si puedo cambiar a otro servidor más rápido también.

es decir:

RAM = cStringIO.StringIO() CHART = plt.figure(.... **code for creating my chart** CHART.savefig(RAM, format=''png'')

He estado usando matplotlib con FigureCanvasAgg back-end.

¡Gracias!


Necesitaba generar rápidamente muchas parcelas también. Descubrí que el multiprocesamiento mejoró la velocidad de trazado con la cantidad de núcleos disponibles. Por ejemplo, si 100 tramas tomaron 10 segundos en un proceso, tardaron ~ 3 segundos cuando la tarea se dividió en 4 núcleos.


Si solo quieres un buffer en bruto, prueba fig.canvas.print_rgb , fig.canvas.print_raw , etc (la diferencia entre los dos es que raw es rgba, mientras que rgb es rgb. También hay print_png , print_ps , etc.)

Esto usará fig.dpi lugar del valor predeterminado de dpi para savefig (100 dpi). Aún así, incluso comparando fig.canvas.print_raw(f) e fig.savefig(f, format=''raw'', dpi=fig.dpi) la versión de print_canvas es marginalmente más rápida, insignificantemente más rápida, ya que no molesta restablecer el color de el parche del eje, etc., que savefig hace por defecto.

Sin embargo, la mayor parte del tiempo dedicado a guardar una figura en un formato crudo es solo dibujar la figura, que no hay forma de moverse.

En cualquier caso, como un ejemplo sin sentido pero divertido, considere lo siguiente:

import matplotlib.pyplot as plt import numpy as np import cStringIO plt.ion() fig = plt.figure() ax = fig.add_subplot(111) num = 50 max_dim = 10 x = max_dim / 2 * np.ones(num) s, c = 100 * np.random.random(num), np.random.random(num) scat = ax.scatter(x,x,s,c) ax.axis([0,max_dim,0,max_dim]) ax.set_autoscale_on(False) for i in xrange(1000): xy = np.random.random(2*num).reshape(num,2) - 0.5 offsets = scat.get_offsets() + 0.3 * xy offsets.clip(0, max_dim, offsets) scat.set_offsets(offsets) scat._sizes += 30 * (np.random.random(num) - 0.5) scat._sizes.clip(1, 300, scat._sizes) fig.canvas.draw()

Si miramos el tiempo de sorteo crudo:

import matplotlib.pyplot as plt import numpy as np import cStringIO fig = plt.figure() ax = fig.add_subplot(111) num = 50 max_dim = 10 x = max_dim / 2 * np.ones(num) s, c = 100 * np.random.random(num), np.random.random(num) scat = ax.scatter(x,x,s,c) ax.axis([0,max_dim,0,max_dim]) ax.set_autoscale_on(False) for i in xrange(1000): xy = np.random.random(2*num).reshape(num,2) - 0.5 offsets = scat.get_offsets() + 0.3 * xy offsets.clip(0, max_dim, offsets) scat.set_offsets(offsets) scat._sizes += 30 * (np.random.random(num) - 0.5) scat._sizes.clip(1, 300, scat._sizes) fig.canvas.draw()

Esto lleva ~ 25 segundos en mi máquina.

Si en cambio volcamos un buffer RGBA crudo a un búfer cStringIO, en realidad es marginalmente más rápido en ~ 22 segundos (¡Esto solo es cierto porque estoy usando un back-end interactivo! De lo contrario, sería equivalente):

import matplotlib.pyplot as plt import numpy as np import cStringIO fig = plt.figure() ax = fig.add_subplot(111) num = 50 max_dim = 10 x = max_dim / 2 * np.ones(num) s, c = 100 * np.random.random(num), np.random.random(num) scat = ax.scatter(x,x,s,c) ax.axis([0,max_dim,0,max_dim]) ax.set_autoscale_on(False) for i in xrange(1000): xy = np.random.random(2*num).reshape(num,2) - 0.5 offsets = scat.get_offsets() + 0.3 * xy offsets.clip(0, max_dim, offsets) scat.set_offsets(offsets) scat._sizes += 30 * (np.random.random(num) - 0.5) scat._sizes.clip(1, 300, scat._sizes) ram = cStringIO.StringIO() fig.canvas.print_raw(ram) ram.close()

Si lo comparamos con el uso de savefig , con un ppp conjunto comparable:

import matplotlib.pyplot as plt import numpy as np import cStringIO fig = plt.figure() ax = fig.add_subplot(111) num = 50 max_dim = 10 x = max_dim / 2 * np.ones(num) s, c = 100 * np.random.random(num), np.random.random(num) scat = ax.scatter(x,x,s,c) ax.axis([0,max_dim,0,max_dim]) ax.set_autoscale_on(False) for i in xrange(1000): xy = np.random.random(2*num).reshape(num,2) - 0.5 offsets = scat.get_offsets() + 0.3 * xy offsets.clip(0, max_dim, offsets) scat.set_offsets(offsets) scat._sizes += 30 * (np.random.random(num) - 0.5) scat._sizes.clip(1, 300, scat._sizes) ram = cStringIO.StringIO() fig.savefig(ram, format=''raw'', dpi=fig.dpi) ram.close()

Esto lleva ~ 23.5 segundos. Básicamente, savefig simplemente establece algunos parámetros predeterminados y llama a print_raw , en este caso, por lo que hay muy poca diferencia.

Ahora, si comparamos un formato de imagen sin procesar con un formato de imagen comprimida (png), vemos una diferencia mucho más significativa:

import matplotlib.pyplot as plt import numpy as np import cStringIO fig = plt.figure() ax = fig.add_subplot(111) num = 50 max_dim = 10 x = max_dim / 2 * np.ones(num) s, c = 100 * np.random.random(num), np.random.random(num) scat = ax.scatter(x,x,s,c) ax.axis([0,max_dim,0,max_dim]) ax.set_autoscale_on(False) for i in xrange(1000): xy = np.random.random(2*num).reshape(num,2) - 0.5 offsets = scat.get_offsets() + 0.3 * xy offsets.clip(0, max_dim, offsets) scat.set_offsets(offsets) scat._sizes += 30 * (np.random.random(num) - 0.5) scat._sizes.clip(1, 300, scat._sizes) ram = cStringIO.StringIO() fig.canvas.print_png(ram) ram.close()

¡Esto demora ~ 52 segundos! Obviamente, hay una gran sobrecarga al comprimir una imagen.

En cualquier caso, este es probablemente un ejemplo innecesariamente complejo ... Creo que solo quería evitar el trabajo real ...