Seite 1 von 2

pyFmGraph (Artistic Last.fm Statistic)

Verfasst: Sonntag 11. November 2007, 14:14
von sonium
Bild

http://pyfmgraph.sourceforge.net/graph2.png (Große Version)

Was ihr hier seht ist ein Graph erstellt aus den Daten die Last.fm so über die Zeit sammelt. Über www.audioscrobbler.net kann man darauf per xml zugreifen. Die Idee da so dar zu stellen ist zwar nicht von mir sondern von www.megamu.com aber nachdem der Typ absolut nicht auf meine Emails geantwortet hat, bin ich nicht drum rum gekommen selbst bei Null anzufangen.

Bis auf die Beschriftung ist das ganze in Python und der Python Imaging Library (PIL) gecodet. Das Programm hab ich freundlicherweise auf Sourceforge gestellt.

Gemacht hab ich den ganzen Aufwand für ein, ziemlich orginelles, Geburtstagsgeschenk. Das ganze hab ich auf zwei Meter Länge geplottet (geht in der Uni recht billig)

Zur Darstellung: Es wird dargestellt wann welcher Künstler wie häufig gehört wurde. Dickere Flächen bedeuten häufiger. Ein Artist hat eine Farbe. Blauere Farben bedeutet dass der Artist zeitlich früher zum ersten mal gehört wurde, rot heißt später.

Nachbearbeitet hab ich das ganze dann noch mit GIMP auf nem 4gb Ram PC, was bei einer Auflösung von 20000x5000 echt das mindeste ist.

EDIT by mawe: Link gefixt

Verfasst: Sonntag 11. November 2007, 14:29
von mawe
Naja, sieht nett aus. Was genau ist die y-Achse? Bei den Farben, "zeitlich früher", ist da die Uhrzeit gemeint?

Verfasst: Sonntag 11. November 2007, 14:36
von sonium
Zeitlich früher mein Uhrzeit, ja. die Breite einer Fläche in Y-Richtung ist die Häufigkeit mit der der Artist gehört wurde.

Verfasst: Sonntag 11. November 2007, 15:13
von Leonidas
Wow, sieht klasse aus. Ein Webinterface wäre jetzt direkt noch besser :D

Verfasst: Sonntag 11. November 2007, 18:08
von lunar
Was man vom Code allerdings nicht sagen kann: Der ist ja grausam (sorry ;) )

Ich werde mal versuchen, da durchzusteigen und ihn zu verbessern. Das Parsen des XML Codes kann man durch die Verwendung von ElementTree schon mal wesentlich übersichtlicher gestalten.

Um die Idee mit dem Webinterface tatsächlich umzusetzen, müsste man das Ganze vor allem erstmal so gestalten, dass man es als Modul verwenden kann. Auch das versuche ich mal umzusetzen.

Da ich allerdings noch ernste Verständnisschwierigkeiten habe, dauert es wohl bis nächstes Wochenende, ehe da greifbare Resultate vorliegen ;)

Verfasst: Sonntag 11. November 2007, 18:22
von BlackJack
Wenn Du schon dabei bist, kannst Du das Backend auch herausziehen und austauschbar machen. Als SVG, PDF oder PS macht sich so eine Grafik sicher auch ganz gut. :-)

Verfasst: Sonntag 11. November 2007, 18:44
von lunar
BlackJack hat geschrieben:Wenn Du schon dabei bist, kannst Du das Backend auch herausziehen und austauschbar machen. Als SVG, PDF oder PS macht sich so eine Grafik sicher auch ganz gut. :-)
Tja, dafür müsste ich erstmal den Code zum Zeichnen verstehen ;) Ich habe noch nie Grafikprogrammierung gemacht. Zudem bräuchte man erstmal verschiedene Bibliotheken... vorerst wird es also höchstens ein PIL Backend geben...

Ich habe noch ganz gut zu tun, den Code überhaupt erstmal in eine anständige, wartbare und verständliche Form zu bringen ;) Erschwert wird die Sache durch die Tatsache, dass ich zur Zeit nur am Wochenende an den PC kann.

Verfasst: Sonntag 11. November 2007, 18:55
von Imperator
Wow, das sieht echt cool aus. War bestimmt sau schwer.

Verfasst: Sonntag 11. November 2007, 19:30
von Y0Gi
Respekt, das sieht sehr ansprechend aus. Einzig der "Septemer" würde mir jeden Tag ein bisschen weh tun, wenn ich das als Riesenposter an der Wand hätte ;)

Verfasst: Sonntag 11. November 2007, 20:23
von sonium
Y0Gi hat geschrieben:Respekt, das sieht sehr ansprechend aus. Einzig der "Septemer" würde mir jeden Tag ein bisschen weh tun, wenn ich das als Riesenposter an der Wand hätte ;)
Da steht September! (Jag mir doch keinen so Schreck ein!)

@lunar: Für Fragen stehe ich jederzeit zur Verfügung. Vielleicht schaff ich demnächst sogar das SVN Repository von SF.net zum laufen zu kriegen. Ich würde mich freuen wenn man zusammenarbeiten könnte. Ne automatische Schriftpositionierung wäre z.B. auch schön.

Svg ist leider nicht möglich da das Rasterizing ein Teil des Algorithmus ist.

Verfasst: Sonntag 11. November 2007, 20:31
von veers
Also bei mir steht da auch "Septemer" - Oben rechts ;)

Verfasst: Sonntag 11. November 2007, 20:50
von sonium
oh shit...

Verfasst: Sonntag 11. November 2007, 21:24
von BlackJack
Wieso sollte SVG (, PDF, PS) nicht möglich sein? Da musst Du halt die Bezierkurven nicht selber berechnen sondern nur die Stützpunkte in Pfade stecken.

Verfasst: Sonntag 11. November 2007, 23:12
von Leonidas
lunar hat geschrieben:Ich habe noch ganz gut zu tun, den Code überhaupt erstmal in eine anständige, wartbare und verständliche Form zu bringen ;)
Hmm, wenn du meinst... ich habe mir mal den Code angesehen.

Meine Libeblingszeile ist glaube ich die folgende:

Code: Alles auswählen

if (artist[i] != 0) or (i == 0) or (i == len_week - 1) or (artist[i-1]) == 0 or (artist[i+1]) == 0:
Da fängt mein gestriger `sed`-Code an, elegant zu wirken ;)

Verfasst: Sonntag 11. November 2007, 23:22
von sonium
wobei zu erwähnen ist, dass die Reihenfolge der Bedingungen entscheidend ist :P
BlackJack hat geschrieben:Wieso sollte SVG (, PDF, PS) nicht möglich sein? Da musst Du halt die Bezierkurven nicht selber berechnen sondern nur die Stützpunkte in Pfade stecken.
Das Problem ist, dass ich die Bezierkurven nicht einfach übereinander stapeln kann, da die Stützpunkte nicht übereinander liegen. Momentan funktioniert es so, dass ich sie einfach pixelweise addiere. SVG wäre mir auch lieber.

Verfasst: Montag 12. November 2007, 08:14
von veers
Würde es nicht reichen wenn du einfach die Stützpunkte addierst?

Verfasst: Montag 12. November 2007, 11:10
von sonium
Ne, weil die eben nicht übereinander liegen. Was ich machen müsste wäre es Bezierkurven in mehrere kleine Bezierkurven zu unterteilen. Und da hab ich mathematische Probleme. Ne Alternative wäre die Bezierkurven in Polygonzüge mit regelmäßigen x-Abständen zu unterteilen. Ich hab das mal in Maple Versucht und das Ergebniss war ziemlich wüst. Hier mal ne Zeichnung zum Problem:

http://homepages.uni-regensburg.de/~hua16585/bezier.svg

Verfasst: Samstag 17. November 2007, 23:38
von lunar
Mein erster Versuch. Das git repo ist hier zu finden.

Die Ausgabe meines Codes sagt mir, dass da noch etwas nicht stimmt. Was, kann ich nicht sagen, der Code zum Zeichnen ist größtenteils 1:1 kopiert und notdürftig in das OOP Korsett gezwängt, da ich ihn immer noch nicht wirklich verstehe. Irgendwo habe ich da wohl was bei der Anpassung übersehen. Morgen werde ich vielleicht nochmal ein bisschen damit spielen, für Tipps wäre ich aber echt dankbar. Ansonsten gibts die fertige Version höchstwahrscheinlich erst nächstes Wochende (wenn überhaupt).

Eine Frage an den OP hätte ich allerdings schon mal: Du programmierst nicht lange in Python, oder? Im Code fallen viele Dinge auf, die gelinde gesagt ziemlich mies sind. Die dauernde Verwendung von range zur aufsteigenden Iteration über Zahlen wäre ja noch zu verschmerzen, aber sowas

Code: Alles auswählen

for nvec in range(len(curve))[1:-1]:
    ...
ist ja grausam :shock: Das tut ja fast schon körperlich weg...

Verfasst: Sonntag 18. November 2007, 14:22
von sonium
Sieht ja echt ganz schick aus mit OOP. Ich hab schon vor einiger Zeit mit Python angefangen, nur hab ich bisher hauptsächlich mit der Python Referenz beschäftigt und mir fehlt halt das know-How z.B. mit der Iterierung.

Zum Zeichencode, das funktioniert so:

(ich hab mal ein Bild gemalt: http://homepages.uni-regensburg.de/~hua16585/graph.svg
)

Als erstes holt er die Daten von Audioscrobbler und konvertiert sie in Vektoren. Diese sind in relativ regelmäßigen Abständen sofern Daten vorhanden waren. Damit Man eine annähernde Kurve bekommt werden jetzt an stellen wo keine Daten vorhanden sind Vektoren mit y-Wert 0 eingefügt (rot). Aber so, dass nicht mehr als zwei Null-Vektoren aufeinander folgen. Der nächste Schritt ist dann Voraussetzung zum zeichnen der Bezier-Kurven. Es werden Linear-Interpolierte Stützvektoren eingezeichnet (blau) an diesen liegen die Bezierkurven später dann tangential an. Jetzt werden Bezierkurven verwendet um Vektoren die die Bezierkurve annähern zu berechnen. Die Auflösung hierfür ist variabel, je grober, desto eckiger werden die Kurven später. Eine gute Erklärung von Bezierkurven findest du hier: http://www.gamedev.net/reference/articl ... le1808.asp

Jetzt besteht jede Kurve aus vielen Vektoren die eine einigermaßen rund sind. Also muss man das ganze nur noch übereinander stapeln.

Dazu werden zwischen den zwei nächstliegenden Vektoren die Pixelpositionen linear interpoliert. (Also Mittels Steigungsdreieck und zentrischer Streckung) Die Y-Werte werden dann einfach addiert.

Jetzt verstehst du sicher auch, warum es schwierig ist das ganze als svg zu exportieren. Die Bezier-Funktion muss nämlich zum übereinander stapeln explizit ausgeführt werden.

Was ich mir vorstellen könnte wäre höchstens, dass es eine Methode gibt eine Bezier kurve in mehrere zu zerlegen, so dass alle die gleiche X-Länge haben. Dann könnte man vielleicht einfach die Stützpunkte addieren.

Hoffe mal die Erklärung war verständlicher als der Code ;)

Verfasst: Sonntag 18. November 2007, 18:45
von lunar
Tja, die Erklärung sagt mir nur bedingt was, dafür reichen meine mathematischen Kenntnisse momentan nicht aus (die Oberstufe ist ne Weile her, das Studium beginnt erst nächstes Jahr, da vergisst man einiges ;) ).

Allerdings habe ich den Bug gefunden, jetzt zeichnet meine Version ihre Graphen ebenfalls korrekt. Die neue Version liegt im Repo, für git-Verweigerer gibts auch noch das Paste. Nächstes Wochenende kann ich mal versuchen, den Text direkt in das Bild zu integrieren. Mittels image.paste sollte das kein allzu großes Problem sein, nur die Platzierung der Text müsste noch optimiert werden. Dabei hoffe ich mal auf deine Hilfe ;)

Das Kommandozeilen-Interface ist auch noch verbesserungsbedürftig, es fehlen Optionen, um z.B. die verwendete Schriftart anzugeben, oder die Verbosity des Loggings.