Eine (kleinere) Beschleunigung würde eine einzelne Zeilensammlung anstelle von 10000 separaten Zeilensammlungen hinzufügen.
Solange alle Zeilen die gleiche Farbpalette haben, können Sie sie zu einer einzigen Zeilensammlung zusammenfassen, wobei jede Zeile einen unabhängigen Farbverlauf haben kann.
Matplotlib ist immer noch langsam für diese Art von Sache. Es ist optimiert für die Ausgabequalität und nicht für die schnelle Zeichenzeit. Sie können jedoch etwas beschleunigen (~ 3x). (?)
So, als Beispiel dafür, wie ich glaube, du bist wahrscheinlich tun es jetzt:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
# Make random number generation consistent between runs
np.random.seed(5)
def main():
numlines, numpoints = 2, 3
lines = np.random.random((numlines, numpoints, 2))
fig, ax = plt.subplots()
for line in lines:
# Add "num" additional segments to the line
segments, color_scalar = interp(line, num=20)
coll = LineCollection(segments)
coll.set_array(color_scalar)
ax.add_collection(coll)
plt.show()
def interp(data, num=20):
"""Add "num" additional points to "data" at evenly spaced intervals and
separate into individual segments."""
x, y = data.T
dist = np.hypot(np.diff(x - x.min()), np.diff(y - y.min())).cumsum()
t = np.r_[0, dist]/dist.max()
ti = np.linspace(0, 1, num, endpoint=True)
xi = np.interp(ti, t, x)
yi = np.interp(ti, t, y)
# Insert the original vertices
indices = np.searchsorted(ti, t)
xi = np.insert(xi, indices, x)
yi = np.insert(yi, indices, y)
return reshuffle(xi, yi), ti
def reshuffle(x, y):
"""Reshape the line represented by "x" and "y" into an array of individual
segments."""
points = np.vstack([x, y]).T.reshape(-1,1,2)
points = np.concatenate([points[:-1], points[1:]], axis=1)
return points
if __name__ == '__main__':
main()
Stattdessen würde ich etwas in dieser Richtung reccomend tun (die einzigen Unterschiede sind in der main
Funktion):
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
# Make random number generation consistent between runs
np.random.seed(5)
def main():
numlines, numpoints = 2, 3
points = np.random.random((numlines, numpoints, 2))
# Add "num" additional segments to each line
segments, color_scalar = zip(*[interp(item, num=20) for item in points])
segments = np.vstack(segments)
color_scalar = np.hstack(color_scalar)
fig, ax = plt.subplots()
coll = LineCollection(segments)
coll.set_array(color_scalar)
ax.add_collection(coll)
plt.show()
def interp(data, num=20):
"""Add "num" additional points to "data" at evenly spaced intervals and
separate into individual segments."""
x, y = data.T
dist = np.hypot(np.diff(x - x.min()), np.diff(y - y.min())).cumsum()
t = np.r_[0, dist]/dist.max()
ti = np.linspace(0, 1, num, endpoint=True)
xi = np.interp(ti, t, x)
yi = np.interp(ti, t, y)
# Insert the original vertices
indices = np.searchsorted(ti, t)
xi = np.insert(xi, indices, x)
yi = np.insert(yi, indices, y)
return reshuffle(xi, yi), ti
def reshuffle(x, y):
"""Reshape the line represented by "x" and "y" into an array of individual
segments."""
points = np.vstack([x, y]).T.reshape(-1,1,2)
points = np.concatenate([points[:-1], points[1:]], axis=1)
return points
if __name__ == '__main__':
main()
Beide Varianten erzeugen eine identische Handlung:
Wenn wir die Anzahl der Zeilen auf 10000 erhöhen, werden wir jedoch deutliche Leistungsunterschiede feststellen.
Verwenden von 10000 Zeilen, mit 3 Punkten jeden und weitere 20 Punkte im gesamten für den Farbverlauf interpolierten (23 Segmente in jeder Zeile) und man die Zeit, um eine Abbildung auf eine PNG speichern es dauert:
Took 10.866694212 sec with a single collection
Took 28.594727993 sec with multiple collections
Also, die Verwendung einer einzelnen Zeile Sammlung wird ein bisschen weniger als eine 3x Beschleunigung in diesem speziellen Fall geben. Es ist nicht hervorragend, aber es ist besser als nichts.
Hier ist der Timing-Code und die Ausgabezahl, für was auch immer es sich lohnt (Die Ausgabezahlen sind nicht ganz identisch wegen der verschiedenen Anordnungen der Zeichnung.Wenn Sie die Kontrolle über z-Ebene benötigen, werden Sie in separaten Zeile Sammlungen halten müssen):
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
import time
# Make random number generation consistent between runs
np.random.seed(5)
def main():
numlines, numpoints = 10000, 3
lines = np.random.random((numlines, numpoints, 2))
# Overly simplistic timing, but timeit is overkill for this exmaple
tic = time.time()
single_collection(lines).savefig('/tmp/test_single.png')
toc = time.time()
print 'Took {} sec with a single collection'.format(toc-tic)
tic = time.time()
multiple_collections(lines).savefig('/tmp/test_multiple.png')
toc = time.time()
print 'Took {} sec with multiple collections'.format(toc-tic)
def single_collection(lines):
# Add "num" additional segments to each line
segments, color_scalar = zip(*[interp(item, num=20) for item in lines])
segments = np.vstack(segments)
color_scalar = np.hstack(color_scalar)
fig, ax = plt.subplots()
coll = LineCollection(segments)
coll.set_array(color_scalar)
ax.add_collection(coll)
return fig
def multiple_collections(lines):
fig, ax = plt.subplots()
for line in lines:
# Add "num" additional segments to the line
segments, color_scalar = interp(line, num=20)
coll = LineCollection(segments)
coll.set_array(color_scalar)
ax.add_collection(coll)
return fig
def interp(data, num=20):
"""Add "num" additional points to "data" at evenly spaced intervals and
separate into individual segments."""
x, y = data.T
dist = np.hypot(np.diff(x - x.min()), np.diff(y - y.min())).cumsum()
t = np.r_[0, dist]/dist.max()
ti = np.linspace(0, 1, num, endpoint=True)
xi = np.interp(ti, t, x)
yi = np.interp(ti, t, y)
# Insert the original vertices
indices = np.searchsorted(ti, t)
xi = np.insert(xi, indices, x)
yi = np.insert(yi, indices, y)
return reshuffle(xi, yi), ti
def reshuffle(x, y):
"""Reshape the line represented by "x" and "y" into an array of individual
segments."""
points = np.vstack([x, y]).T.reshape(-1,1,2)
points = np.concatenate([points[:-1], points[1:]], axis=1)
return points
if __name__ == '__main__':
main()
Ich vermute, dass Sie eine Einschränkung von 'matplotlib' getroffen haben, aber glaube nicht, Das ist dein Hauptproblem. Wenn Sie 10k-Zeilen haben, selbst wenn Sie sie mit 1px Breite gezeichnet haben, würde das Ausrichten eine große Anzeige/einen großen Ausdruck erfordern, um sie alle unabhängig voneinander sehen zu können. Selbst wenn Sie einen Weg finden könnten, diese Handlung zu machen, würden Sie nicht in der Lage sein, es vernünftig zu betrachten. Gibt es einen Weg, wie Sie Ihre Daten grobkörnig machen können? – tacaswell
Haben Sie versucht, eine einzelne Zeilensammlung anstelle von 10000 separaten Zeilensammlungen hinzuzufügen? Es ist immer noch langsam, aber es ist schneller. Es ist auch reaktionsschneller beim Schwenken und Zoomen. –
@JoeKington: Netter Trick. – Developer