Wie kann ich ein 2D-Array als Bild mit Matplotlib darstellen, dessen y-Skalierung relativ zur Potenz von zwei ist der y-Wert?
Zum Beispiel hat die erste Zeile meines Arrays eine Höhe im Bild von 1, die zweite Zeile hat eine Höhe von 4 usw. (Einheiten sind irrelevant) Es ist nicht einfach, mit Worten zu erklären, also schau dir bitte dieses Bild an (das ist die Art von Ergebnis, das ich will):
alt text http://support.sas.com /rnd/app/da/new/802ce/iml/chap1/images/wavex1k.gif
Wie Sie sehen können, ist die erste Zeile 2 mal kleiner als die obere und so weiter.
Für diejenigen, die daran interessiert sind, warum ich das versuche:
Ich habe ein ziemlich großes Array (10, 700000) von Floats, die die diskreten Wavelet-Transformationskoeffizienten einer Sounddatei darstellen. Ich versuche, das Skalogramm mit diesen Koeffizienten zu zeichnen. Ich könnte das Array x-mal kopieren, bis ich die gewünschte Bildreihengröße erreicht habe, aber der Speicher kann nicht so viele Informationen enthalten ...
Haben Sie versucht, die Achse zu transformieren? Zum Beispiel:
%Vor%Dies bedeutet, dass es Lücken in den Daten für die nicht existenten Koordinaten geben muss, es sei denn, es gibt eine Möglichkeit, eine Transformationsfunktion anstelle von nur Listen (nie probiert) bereitzustellen.
Bearbeiten :
Ich gebe zu, es war nur eine Führung, keine vollständige Lösung. Hier ist, was ich in mehr Details meinte.
Nehmen wir an, Sie haben Ihre Daten in einem Array, a
. Sie können eine Transformation wie diese verwenden:
Im Grunde wird die erste Koordinate eines Arrays oder einer Liste mit der mylog2
-Funktion transformiert (die Sie nach Belieben transformieren können - sie ist zu Hause als Vereinfachung von log2 erstellt). Der Vorteil ist, dass Sie das für eine andere Transformation wiederverwenden können, wenn Sie es brauchen, und Sie können es auch leicht kontrollieren.
Ordnen Sie dann Ihr Array diesem zu, das keine Kopie, sondern eine lokale Referenz in der Instanz erstellt:
%Vor%Jetzt können Sie es anzeigen, zum Beispiel:
%Vor%Hier ist ein Beispiel (mit einem Array mit zufälligen Werten):
Alternativtext http://img691.imageshack.us/img691/8883/clipboard01f.png
Sie können sich matplotlib.image.NonUniformImage ansehen. Aber das hilft nur mit einer ungleichmäßigen Achse - ich denke nicht, dass du in der Lage sein wirst, adaptiv so zu zeichnen, wie du es willst (ich denke, dass jeder Punkt im Bild immer die gleiche Fläche haben wird - also wirst du es tun) müssen die breiteren Reihen mehrmals haben). Gibt es einen Grund, warum Sie das gesamte Array plotten müssen? Offensichtlich wird das vollständige Detail in keinem Plot angezeigt - daher würde ich vorschlagen, die ursprüngliche Matrix stark zu verkleinern, so dass Sie Zeilen nach Bedarf kopieren können, um das Bild zu erhalten, ohne den Speicher zu verlieren.
Der beste Weg, ein Scalogramm mit matplotlib zu erstellen, ist die Verwendung von imshow
, ähnlich der Implementierung von specgram
. Die Verwendung von Rechtecken ist langsam, da Sie für jeden Wert eine separate Glyphe erstellen müssen. Genauso wenig möchten Sie Dinge in ein einheitliches NumPy-Array brennen, da Ihnen wahrscheinlich schnell der Speicher ausgehen wird, da Ihr höchster Pegel ungefähr die Hälfte Ihres Signals beträgt.
Hier ist ein Beispiel mit SciPy und PyWavelets :
%Vor%Sie können Werte auch adaptiv pro Level skalieren.
Das funktioniert ziemlich gut für mich. Das einzige Problem, das ich habe, ist, dass Matplotlib einen haarfeinen Raum zwischen den Ebenen schafft. Ich suche immer noch nach einer Möglichkeit, das zu beheben.
P.S. - Obwohl diese Frage jetzt ziemlich alt ist, habe ich mir gedacht, dass ich hier antworten würde, weil diese Seite auf Google erschien, als ich nach einer Methode zur Erstellung von Scalogrammen mit MPL suchte.
Wenn Sie sowohl als auch speichern möchten, können Sie die Zeichnung "von Hand" machen. Mit Matplotlib können Sie Rechtecke zeichnen (das wären Ihre "rechteckigen Pixel"):
%Vor%Beachten Sie, dass die Extents der Achsen nicht durch add_patch () festgelegt werden, Sie können sie jedoch selbst auf die gewünschten Werte setzen (axes.set_xlim, ...).
PS: Ich sehe aus wie thropes Antwort (matplotlib.image.NonUniformImage) kann tatsächlich tun, was Sie wollen, auf eine einfachere Weise als die hier beschriebene "manuelle" Methode!
Tags und Links python matplotlib