matrices graficos graficas graficar coordenadas python matplotlib plot line

python - graficos - matplotlib title position



Matplotlib: trazar numerosos segmentos de lĂ­nea desconectados con diferentes colores (4)

El plot función permite dibujar múltiples líneas en una llamada, si sus datos están solo en una lista, simplemente descomprímalo al pasarlo a la plot :

In [315]: data=[(1, 1), (2, 3), ''r'', #assuming points are (1,2) (1,3) actually and, #here they are in form of (x1, x2), (y1, y2) ...: (2, 2), (4, 5), ''g'', ...: (5, 5), (6, 7), ''b'',] In [316]: plot(*data) Out[316]: [<matplotlib.lines.Line2D at 0x8752870>, <matplotlib.lines.Line2D at 0x8752a30>, <matplotlib.lines.Line2D at 0x8752db0>]

Tengo un conjunto de registros de datos como este:

(s1, t1), (u1, v1), color1 (s2, t2), (u2, v2), color2 . . . (sN, tN), (uN, vN), colorN

En cualquier registro, los primeros dos valores son los puntos finales de un segmento de línea, el tercer valor es el color de ese segmento de línea. Más específicamente, (sn, tn) son las coordenadas xy del primer punto final, (un, vn) son las coordenadas xy del segundo punto final. Además, el color es un rgb con valor alfa.

En general, dos segmentos de línea están desconectados (lo que significa que sus puntos finales no coinciden necesariamente).

Cómo trazar estos datos usando matplotlib con una sola llamada de plot (o la menor cantidad posible) ya que podría haber potencialmente miles de registros.

Intenta

Preparar los datos en una gran lista y llamar a la plot contra de ella es demasiado lenta. Por ejemplo, el siguiente código no pudo finalizar en un tiempo razonable:

import numpy as np import matplotlib.pyplot as plt data = [] for _ in xrange(60000): data.append((np.random.rand(), np.random.rand())) data.append((np.random.rand(), np.random.rand())) data.append(''r'') print ''now plotting...'' # from now on, takes too long plt.plot(*data) print ''done'' #plt.show()

Pude acelerar la representación de la trama utilizando el truco de inserción Ninguno de la siguiente manera:

import numpy as np import matplotlib.pyplot as plt from timeit import timeit N = 60000 _s = np.random.rand(N) _t = np.random.rand(N) _u = np.random.rand(N) _v = np.random.rand(N) x = [] y = [] for s, t, u, v in zip(_s, _t, _u, _v): x.append(s) x.append(u) x.append(None) y.append(t) y.append(v) y.append(None) print timeit(lambda:plt.plot(x, y), number=1)

Esto se ejecuta en menos de un segundo en mi máquina. Todavía tengo que descubrir cómo incrustar los valores de color (RGB con canal alfa).


He probado algunos buenos motores de renderizado 2D disponibles en Python 3, mientras busco una solución rápida para una etapa de salida en Deep Learning & GAN orientado a la imagen.

Uso de la siguiente referencia: tiempo para procesar 99 líneas en una imagen fuera de pantalla de 256x256 (o lo que sea más efectivo) con y sin anti-alias.

Los resultados, en orden de eficiencia en mi laptop oldish x301:

  • PyGtk2: ~ 2500 FPS, (Python 2, GTK 2, no estoy seguro de cómo obtener AA)
  • PyQt5: ~ 1200 FPS, ~ 350 con Antialias
  • PyQt4: ~ 1100 FPS, ~ 380 con AA
  • El Cairo: ~ 750 FPS, ~ 250 con AA (solo un poco más rápido con ''AA RÁPIDO'')
  • PIL: ~ 600 FPS

La línea de base es un ciclo que toma ~ 0.1 ms (10,000 FPS) recuperando números aleatorios y llamando a los primitivos.

Código básico para PyGtk2:

from gtk import gdk import random WIDTH = 256 def r255(): return int(256.0*random.random()) cmap = gdk.Colormap(gdk.visual_get_best_with_depth(24), True) black = cmap.alloc_color(''black'') white = cmap.alloc_color(''white'') pixmap = gdk.Pixmap(None, WIDTH, WIDTH, 24) pixmap.set_colormap(cmap) gc = pixmap.new_gc(black, line_width=2) pixmap.draw_rectangle(gc, True, -1, -1, WIDTH+2, WIDTH+2); gc.set_foreground(white) for n in range(99): pixmap.draw_line(gc, r255(), r255(), r255(), r255()) gdk.Pixbuf(gdk.COLORSPACE_RGB, False, 8, WIDTH, WIDTH ).get_from_drawable(pixmap, cmap, 0,0, 0,0, WIDTH, WIDTH ).save(''Gdk2-lines.png'',''png'')

Y aquí está para PyQt5:

from PyQt5.QtCore import Qt from PyQt5.QtGui import * import random WIDTH = 256.0 def r255(): return WIDTH*random.random() image = QImage(WIDTH, WIDTH, QImage.Format_RGB16) painter = QPainter() image.fill(Qt.black) painter.begin(image) painter.setPen(QPen(Qt.white, 2)) #painter.setRenderHint(QPainter.Antialiasing) for n in range(99): painter.drawLine(WIDTH*r0to1(),WIDTH*r0to1(),WIDTH*r0to1(),WIDTH*r0to1()) painter.end() image.save(''Qt5-lines.png'', ''png'')

Y aquí está Python3-Cairo para completar:

import cairo from random import random as r0to1 WIDTH, HEIGHT = 256, 256 surface = cairo.ImageSurface(cairo.FORMAT_A8, WIDTH, HEIGHT) ctx = cairo.Context(surface) ctx.scale(WIDTH, HEIGHT) # Normalizing the canvas ctx.set_line_width(0.01) ctx.set_source_rgb(1.0, 1.0, 1.0) ctx.set_antialias(cairo.ANTIALIAS_NONE) #ctx.set_antialias(cairo.ANTIALIAS_FAST) ctx.set_operator(cairo.OPERATOR_CLEAR) ctx.paint() ctx.set_operator(cairo.OPERATOR_SOURCE) for n in range(99): ctx.move_to(r0to1(), r0to1()) ctx.line_to(r0to1(), r0to1()) ctx.stroke() surface.write_to_png(''Cairo-lines.png'')


OK, terminé rasterizando las líneas en una imagen PIL antes de convertirla en una matriz numpy:

from PIL import Image from PIL import ImageDraw import random as rnd import numpy as np import matplotlib.pyplot as plt N = 60000 s = (500, 500) im = Image.new(''RGBA'', s, (255,255,255,255)) draw = ImageDraw.Draw(im) for i in range(N): x1 = rnd.random() * s[0] y1 = rnd.random() * s[1] x2 = rnd.random() * s[0] y2 = rnd.random() * s[1] alpha = rnd.random() color = (int(rnd.random() * 256), int(rnd.random() * 256), int(rnd.random() * 256), int(alpha * 256)) draw.line(((x1,y1),(x2,y2)), fill=color, width=1) plt.imshow(np.asarray(im), origin=''lower'') plt.show()

Esta es, de lejos, la solución más rápida y se adapta perfectamente a mis necesidades en tiempo real. Una advertencia es que las líneas se dibujan sin anti-aliasing.


use LineCollection :

import numpy as np import pylab as pl from matplotlib import collections as mc lines = [[(0, 1), (1, 1)], [(2, 3), (3, 3)], [(1, 2), (1, 3)]] c = np.array([(1, 0, 0, 1), (0, 1, 0, 1), (0, 0, 1, 1)]) lc = mc.LineCollection(lines, colors=c, linewidths=2) fig, ax = pl.subplots() ax.add_collection(lc) ax.autoscale() ax.margins(0.1)

aquí está el resultado: