Seite 1 von 1
Farbvektor an Plot-Befehl übergeben
Verfasst: Mittwoch 21. Mai 2014, 11:13
von mcatis
Hallo Leute,
ich habe mit matplotlib-Basmap eine Karte erzeugt und will dort animiert Markers mit verschiedenen Farben drauf malen. Soweit klappt das auch alles.
Nur meckert er bei der Übergabe des Color-Vektors, dass er RGBA haben will.
Hier mein Code:
Code: Alles auswählen
l, = m.plot([], [], c=[], markersize=3)
xx=[]
yy=[]
ww=[]
for i in range(len(a)):
print longitude[i],latitude[i]
xpt,ypt = m(longitude[i],latitude[i])
xx.append(xpt)
yy.append(ypt)
ww.append(float(weight[i]/100))
data = np.vstack([xx,yy,ww])
colormap = np.array(["0.35","0.78","0.35","0.78","0.35","0.78","0.35","0.78","0.35","0.78",
"0.35","0.78","0.35","0.78","0.35","0.78","0.35","0.78","0.35","0.78",
"0.35","0.78","0.35","0.78","0.35","0.78","0.35","0.78","0.35","0.78"])
def animate(num, data, point):
num = num+1
print num
print data
point.set_data(data[0,:num],data[1,:num])
#print data[2,:num+1]
print data[2,:num]
point.set_color(colormap)
return point,
ani = animation.FuncAnimation(fig, animate, frames=len(data[1]), blit=True, fargs=(data,l), interval=500, repeat=False)
Es kommt der Fehler:
ValueError: to_rgba: Invalid rgba arg "['0.35' '0.78' '0.35' '0.78' '0.35' '0.78' '0.35' '0.78' '0.35' '0.78'
'0.35' '0.78' '0.35' '0.78' '0.35' '0.78' '0.35' '0.78' '0.35' '0.78'
'0.35' '0.78' '0.35' '0.78' '0.35' '0.78' '0.35' '0.78' '0.35' '0.78']"
number in rbg sequence outside 0-1 range
Hat jemand eine Idee, wie ich den Vektor übergebe. Er muss ja die Farbinfo von Schritt zu Schritt beibehalten, wie bei den Koordinaten.
1. Marker zb rot, 2. Marker grün (aber er muss dann trotzdem den 1. rot lassen). Ich hatte es geschafft die Farbe zu ändern, aber dann hat er das auf alle Marker angewendet
Kann jemand helfen?
Lg
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Mittwoch 21. Mai 2014, 12:19
von BlackJack
@mcatis: Das ist alles sehr unvollständig. Man wüsste ohne raten ja nicht einmal wo `set_color()` dokumentiert ist. Also schau Du doch mal nach: Was sagt die Dokumentation dazu?
Ein Array mit Zeichenketten scheint mir auf jeden Fall falsch zu sein, selbst wenn das nur vier Werte für RGBA enthalten würde.
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Mittwoch 21. Mai 2014, 14:48
von mcatis
Hallo BlackJack,
hier der komplette Quellcode:
Code: Alles auswählen
import matplotlib
matplotlib.use('Agg')
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import matplotlib.animation as animation
lon = [7.3, 8.7, 8.4, 11.2]
lat = [52.9, 52.0, 53.8, 50.9]
fig = plt.figure(figsize=(8,8),facecolor='w')
m = Basemap(llcrnrlon=4.0,urcrnrlon=15.0,llcrnrlat=46.0,urcrnrlat=56.0,\
rsphere=(6378137.00,6356752.3142),\
resolution='l',projection='merc',\
lat_ts=0.,suppress_ticks=True)
m.drawmapboundary(fill_color='w')
m.drawcoastlines(linewidth=0.3)
l, = m.plot([], [], c=[], marker="+", markersize=3)
xx = []
yy = []
for i in range(len(lon)):
xpt,ypt = m(lon[i],lat[i])
xx.append(xpt)
yy.append(ypt)
data = np.vstack([xx,yy])
colormap = np.array(["0.35","0.78","0.35","0.78","0.35","0.78","0.35","0.78","0.35","0.78",
"0.35","0.78","0.35","0.78","0.35","0.78","0.35","0.78","0.35","0.78",
"0.35","0.78","0.35","0.78","0.35","0.78","0.35","0.78","0.35","0.78"])
def animate(num, data, point):
num = num+1
point.set_data(data[0,:num],data[1,:num])
point.set_color('r') # --> geht (aber alles rot)
#point.set_color(colormap) # --> geht nicht
return point,
ani = animation.FuncAnimation(fig, animate, frames=len(data[1]), blit=True, fargs=(data,l), interval=500, repeat=False)
ani.save('animation_markers.gif', writer='imagemagick')
Hoffe das wird jetzt klarer. Es ist eine lauffähige Version auf jeden Fall.
Nachtrag:
Ich habe mal die Strings weggenommen im colormap-Vektor und dann das hier gemacht:
Dann plottet er alles grün.
Hingegen
verursacht den Fehler:
ValueError: to_rgba: Invalid rgba arg "[ 0.35]"
need more than 1 value to unpack
Lg mcatis
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Mittwoch 21. Mai 2014, 15:33
von mcatis
Ich hab das alles mit dem return mal wegelassen und zur Vereinfachung den Plot-Befehl mit in die Animations-Funktion gezogen:
Code: Alles auswählen
def get_marker_color(nn):
if nn < 2:
return (0.11)
elif nn < 3:
return (0.55)
else:
return (0.99)
markers = []
def animate(num):
num = num+1
marker_string = get_marker_color(num)
markers.append(marker_string)
m.plot(data[0,:num],data[1,:num], c=float(str(markers[:num])), marker="o", markersize=3)
ValueError: could not convert string to float: [0.11]
Er kommt einfach mit diesen Strings und floats nicht klar.
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Mittwoch 21. Mai 2014, 15:46
von EyDu
mcatis hat geschrieben:Er kommt einfach mit diesen Strings und floats nicht klar.
Du meinst, dass du nicht mit den Strings klar kommst

Schau dir doch die Fehlermeldung an, da steht ganz klar, dass "[0.11]" nicht in einen String umgewandelt werden kann. Jetzt solltest du dir die Frage stellen, warum du eine Liste bekommst. Zerlege Zeile 15 man in Einzelstücke, dann siehst du das Problem.
Allerdings hättest du das Problem gar nicht erst, wenn du von Anfang an vernünftig Arbeitest. Das Problem ist ja nicht, dass du mit Strings arbeiten musst, sondern dass du an dieser Stelle überhaupt strings in die Hände bekommst und dass es nicht von Anfang an floats sind.
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Mittwoch 21. Mai 2014, 16:43
von mcatis
Ja, das hab ich ja schon alles durch. Auch reine floats gehen nicht, wie folgendes Programm zeigt:
Code: Alles auswählen
import matplotlib
matplotlib.use('Agg')
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import matplotlib.animation as animation
lon = [7.3, 8.7, 8.4, 11.2]
lat = [52.9, 52.0, 53.8, 50.9]
fig = plt.figure(figsize=(8,8),facecolor='w')
m = Basemap(llcrnrlon=4.0,urcrnrlon=15.0,llcrnrlat=46.0,urcrnrlat=56.0,\
rsphere=(6378137.00,6356752.3142),\
resolution='l',projection='merc',\
lat_ts=0.,suppress_ticks=True)
m.drawmapboundary(fill_color='w')
m.drawcoastlines(linewidth=0.3)
l, = m.plot([], [], c=[], marker="+", markersize=3)
xx = []
yy = []
for i in range(len(lon)):
xpt,ypt = m(lon[i],lat[i])
xx.append(xpt)
yy.append(ypt)
data = np.vstack([xx,yy])
colormap = np.array([0.35,0.78,0.35,0.78,0.35,0.78,0.35,0.78,0.35,0.78,
0.35,0.78,0.35,0.78,0.35,0.78,0.35,0.78,0.35,0.78,
0.35,0.78,0.35,0.78,0.35,0.78,0.35,0.78,0.35,0.78])
def animate(num, data, point):
num = num+1
point.set_data(data[0,:num],data[1,:num])
#point.set_color('r') # --> geht (aber alles rot)
point.set_color(colormap[:num]) # --> geht nicht
return point,
ani = animation.FuncAnimation(fig, animate, frames=len(data[1]), blit=True, fargs=(data,l), interval=500, repeat=False)
Fehler:
ValueError: to_rgba: Invalid rgba arg "[ 0.35]"
need more than 1 value to unpack
Lg
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Mittwoch 21. Mai 2014, 16:52
von EyDu
Die Fehlermeldung nennt dir doch das Problem: Statt der Stringrepräsentation einer Liste, übergibst du nun eine einelementige Liste. Es wird aber ein Wert erwartet, der in RGBA umgewandelt werden kann.
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Mittwoch 21. Mai 2014, 17:27
von mcatis
Wie sieht denn eine "Stringrepräsentation einer Liste" bzw. "ein Wert, der in RGBA umgewandelt werden kann" aus?

Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Mittwoch 21. Mai 2014, 17:34
von BlackJack
@mcatis: Bezüglich der Datentypen solltest Du mal ein Python-Grundlagentutorial durcharbeiten.
RGBA sind ja normalerweise vier Werte, für jede Komponente Einer. Mal anders herum gefragt, was hättest Du denn bei einer Funktion die RGBA erwartet bei [0.35] erwartet wie die Farbe aussieht und zustande kommt?
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Mittwoch 21. Mai 2014, 17:38
von mcatis
Ich weiß das ein RGBA-Wert 4 Werte hat! Das soll kein RGBA werden sondern ein Grauwert.
Die kann man ja bekanntlich mit 0.0 bis 1.0 angeben, z.B color='0.67'.
Will nur wissen wie ich dem sagen soll, dass er die Werte nimmt. Und nicht irgndwas von RGBA erwartet. Weiß nicht was er von mir will. Ich hab ihm nie gesagt
das ich ein RGBA-Wert nehmen möchte

Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Mittwoch 21. Mai 2014, 18:59
von BlackJack
@mcatis: Eine Zeichenkette mit einer Zahlrepräsentation ist halt nicht das gleiche wie eine Liste oder ein Array mit diesem Wert als einzigen Element. Und wenn Du eine Sequenz übergibst, dann sagst Du im Grunde schon das Du eine RGB- oder RGBA-Farbe übergeben möchtest, denn so werden die übergeben. Steht so in der Dokumentation: Sequenzen mit 3 oder 4 Werten sind RGB bzw. RGBA-Angaben.
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Mittwoch 21. Mai 2014, 23:41
von mcatis
Und wie müsste ich es stattdessen schreiben? Ich sehe ja keine Vorschläge ?
Lg
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Donnerstag 22. Mai 2014, 06:24
von Sirius3
@mcatis: Du mußt Dir halt überlegen, wie man einen Grauwert in einen RGB-Wert umrechnet.
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Donnerstag 22. Mai 2014, 08:16
von BlackJack
@mcatis: Oder den Grauwert als *eine* Zeichenkette mit einer Zahldarstellung zwischen 0.00 und 1.00 übergeben.
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Donnerstag 22. Mai 2014, 10:57
von mcatis
So, hab es jetzt versucht mit HEX-Werten in einem Array und die dann nach RGB umgerechnet:
Code: Alles auswählen
def hex_to_RGB(hex):
return [int(hex[i:i+2], 16) for i in range(1,6,2)]
colormap = np.array(['#550000','#C0C0C0','#550000','#C0C0C0','#550000','#C0C0C0','#550000','#C0C0C0','#550000','#C0C0C0',
'#550000','#C0C0C0','#550000','#C0C0C0','#550000','#C0C0C0','#550000','#C0C0C0','#550000','#C0C0C0',
'#550000','#C0C0C0','#550000','#C0C0C0','#550000','#C0C0C0','#550000','#C0C0C0','#550000','#C0C0C0'])
hexcolor = []
for i in range(len(colormap)):
hexcolor.append(hex_to_RGB(colormap[i]))
def animate(num, data, point):
num = num+1
point.set_data(data[0,:num],data[1,:num])
point.set_color(hexcolor[:num])
return point,
ani = animation.FuncAnimation(fig, animate, frames=len(data[1]), blit=True, fargs=(data,l), interval=500, repeat=False)
ani.save('test.gif', writer='imagemagick')
Es kommt wieder die Fehlermeldung
ValueError: to_rgba: Invalid rgba arg "[[85, 0, 0]]"
need more than 1 value to unpack
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Donnerstag 22. Mai 2014, 12:37
von BlackJack
@mcatis: Weil Du immer noch den gleichen Fehler machst: Ein Array mit einem Element ist nicht das gleiche wie ein Element.
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Donnerstag 22. Mai 2014, 12:39
von EyDu
Du übergibst schon wieder eine Liste, welche eine Liste enthält. Du solltest unbedingt noch einmal die Grundlagen von Indexzugriffen durcharbeiten und die Unterschiede von ``data
``, ``data[i:]`` und ``data[:i]`` verstehen. Warum machst du überhaupt den Umweg über ein numpy-Array, wenn es eine einfache Liste auch tun würde?
Das Muster
ist in Python ein Anti-Pattern. Du kannst direkt über Elemente einer Liste iterieren. Wenn du doch mal den Index brauchst, dann verwende die enumerate-Funktion.
Und bitte zeige immer die gesamte Fehlermeldung und zwar inklusive des gesamten Tracebacks, nicht nur den Teil, den du für wichtig erachtest. Dort stehen noch viel mehr Informationen, zum Beispiel *wo* der Fehler auftritt, drin.
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Donnerstag 22. Mai 2014, 12:56
von mcatis
Also so klappt's:
Code: Alles auswählen
import matplotlib
matplotlib.use('Agg')
import matplotlib.cm as cm
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import matplotlib.animation as animation
lon = [7.3, 8.7, 8.4, 11.2]
lat = [52.9, 52.0, 53.8, 50.9]
fig = plt.figure(figsize=(8,8),facecolor='w')
m = Basemap(llcrnrlon=4.0,urcrnrlon=15.0,llcrnrlat=46.0,urcrnrlat=56.0,\
rsphere=(6378137.00,6356752.3142),\
resolution='l',projection='merc',\
lat_ts=0.,suppress_ticks=True)
m.drawmapboundary(fill_color='w')
m.drawcoastlines(linewidth=0.3)
l, = m.plot([], [], c=[], marker="+", markersize=3)
xx = []
yy = []
for i in range(len(lon)):
xpt,ypt = m(lon[i],lat[i])
xx.append(xpt)
yy.append(ypt)
data = np.vstack([xx,yy])
colormap = ('0.1','0.3','0.6','0.9','0.35','0.78','0.35','0.78','0.35','0.78',
'0.35','0.78','0.35','0.78','0.35','0.78','0.35','0.78','0.35','0.78',
'0.35','0.78','0.35','0.78','0.35','0.78','0.35','0.78','0.35','0.78')
def animate(num, data, point):
num = num+1
point.set_data(data[0,:num],data[1,:num])
point.set_color(colormap[num])
return point,
ani = animation.FuncAnimation(fig, animate, frames=len(data[1]), blit=True, fargs=(data,l), interval=500, repeat=False)
ani.save('test.gif', writer='imagemagick')
Aber das hatte ich ja schon mal. Dann setzt er die Farben zwar, aber ich verliere die Information der ersten Farben.
Er zeichnet den 1. Marker in der korrekten Farbe. Dann kommt der 2. Marker: Auch hier nimmt er die korrekte Farbe, setzt dann aber den 1. in der gleichen Farbe wie
den 2. Genau das ist ja das Problem. Deshalb wollte ich ähnlich wie bei den data-Vektoren für die lat-lon-Infos auch bei den Farben einen Vektor übergeben
der sich von Durchlauf zu Durchlauf weiter "aufbläht".
Wie kann ich denn erreichen, dass er die Farbe des 1. Markers nicht überschreibt?
Lg und danke schonmal für alles.
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Donnerstag 22. Mai 2014, 13:53
von BlackJack
@mcatis: Das geht mit `plot()` gar nicht. Ich habe gerade etwas gemacht was man vielleicht viel früher mal hätte machen sollen: In die Dokumentation geschaut. Ich ging ja davon aus das Du das setzen von `c` auf eine *Liste* schon mal nicht-animiert ausprobiert hast, aber das geht grundsätzlich nicht. Die Dokumentation von `plot()` ist da eigentlich auch recht deutlich das dort *ein* Farbwert für die *Linie* erwartet wird. Das was Du `point` genannt hast ist ein `Line2D`-Exemplar. Ist etwas irreführend das `point` zu nennen.
Was Du wahrscheinlich möchtest ist ein `scatter()`-Plot. *Da* sagt die Dokumentation nämlich das man auch eine Sequenz von Farben angeben kann.
Re: Farbvektor an Plot-Befehl übergeben
Verfasst: Donnerstag 22. Mai 2014, 15:35
von mcatis
Gut, danke. Mit einem scatter funktioniert es dann auch.
Lieben Dank für eure Hilfe.