pyFmGraph (Artistic Last.fm Statistic)

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
sonium
User
Beiträge: 66
Registriert: Mittwoch 27. Oktober 2004, 21:04

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
- http://bash.org/?400459
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Naja, sieht nett aus. Was genau ist die y-Achse? Bei den Farben, "zeitlich früher", ist da die Uhrzeit gemeint?
sonium
User
Beiträge: 66
Registriert: Mittwoch 27. Oktober 2004, 21:04

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.
- http://bash.org/?400459
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Wow, sieht klasse aus. Ein Webinterface wäre jetzt direkt noch besser :D
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
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 ;)
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. :-)
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.
Imperator
User
Beiträge: 275
Registriert: Montag 20. August 2007, 14:43
Kontaktdaten:

Wow, das sieht echt cool aus. War bestimmt sau schwer.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

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 ;)
sonium
User
Beiträge: 66
Registriert: Mittwoch 27. Oktober 2004, 21:04

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.
- http://bash.org/?400459
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

Also bei mir steht da auch "Septemer" - Oben rechts ;)
[url=http://29a.ch/]My Website - 29a.ch[/url]
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
sonium
User
Beiträge: 66
Registriert: Mittwoch 27. Oktober 2004, 21:04

oh shit...
- http://bash.org/?400459
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.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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 ;)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
sonium
User
Beiträge: 66
Registriert: Mittwoch 27. Oktober 2004, 21:04

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.
- http://bash.org/?400459
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

Würde es nicht reichen wenn du einfach die Stützpunkte addierst?
[url=http://29a.ch/]My Website - 29a.ch[/url]
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
sonium
User
Beiträge: 66
Registriert: Mittwoch 27. Oktober 2004, 21:04

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
- http://bash.org/?400459
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...
sonium
User
Beiträge: 66
Registriert: Mittwoch 27. Oktober 2004, 21:04

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 ;)
- http://bash.org/?400459
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.
Antworten