Matplotlib: построение множества несвязанных сегментов линии с разными цветами

У меня есть набор записей данных:

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

В любой записи первые два значения являются конечными точками сегмента линии, третье значение – цвет этого сегмента линии. Более конкретно, (sn, tn) – координаты xy первой конечной точки, (un, vn) – координаты xy второго конца. Кроме того, цвет представляет собой rgb с альфа-значением.

В общем, любые два сегмента линии отключены (что означает, что их конечные точки не обязательно совпадают).

Как построить эти данные с помощью matplotlib с помощью одного вызова plot (или как можно меньше), поскольку могут быть потенциально тысячи записей.

попытки

Подготовка данных в одном большом списке, а вызов plot против него слишком медленный. Например, следующий код не смог закончить в разумные сроки:

 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() 

Мне удалось ускорить рендеринг сюжета, используя трюк « Нет» :

 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) 

Это выполняется через секунду на моей машине. Мне еще нужно выяснить, как вставлять значения цвета (RGB с альфа-каналом).

4 Solutions collect form web for “Matplotlib: построение множества несвязанных сегментов линии с разными цветами”

используйте 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) 

вот результат:

введите описание изображения здесь

plot функции позволяет рисовать несколько строк в одном вызове, если ваши данные находятся только в списке, просто распакуйте его, передав его на 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>] 

введите описание изображения здесь

Хорошо, я закончил растеризацию строк на изображении PIL, прежде чем преобразовать его в массив 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() 

Это, безусловно, самое быстрое решение, и оно идеально подходит для меня в реальном времени. Одно из предостережений – это то, что линии рисуются без сглаживания.

Я попробовал несколько хороших движков 2D рендеринга, доступных на Python 3, ища быстрое решение для выходного этапа в ориентированном на изображение Deep Learning & GAN.

Используя следующий контрольный показатель: время для рендеринга 99 строк в 256×256 за пределами изображения (или что-то более эффективное) с и без сглаживания.

Результаты, в порядке эффективности на моем старом ноутбуке x301:

  • PyGtk2: ~ 2500 FPS, (Python 2, GTK 2, не уверен, как получить AA)
  • PyQt5: ~ 1200 FPS, ~ 350 с Antialias
  • PyQt4: ~ 1100 FPS, ~ 380 с AA
  • Каир: ~ 750 FPS, ~ 250 с AA (только немного быстрее с «FAST» AA)
  • PIL: ~ 600 FPS

Базой является цикл, который принимает ~ 0,1 мс (10 000 FPS), извлекает случайные числа и вызывает примитивы.

Базовый код для 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') 

И вот для 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') 

И вот Python3-Cairo для полноты:

 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') 
  • Определение matplotlib.pyplot.axes.bbox
  • Как получить координаты x и y из графика разметки matplotlib с помощью plt.gca ()?
  • Улучшить размер / интервал подзаголовка со многими подзадачами в matplotlib
  • Как нарисовать вероятностные распределения с numpy / matplotlib?
  • OSError: Текстовый файл занят бродягой с синхронизированной папкой
  • Python threading - возврат управления терминалу при сохранении рамки
  • Matplotlib, так что ось журнала имеет только незначительные метки меток в указанных точках. Также измените размер ярлыков меток в colorbar
  • Как / Где скачать Pylab для Python 2.7 на Win32?
  • Python - лучший язык программирования в мире.