Seite 1 von 1

3D Scatterplot eines 2D-Arrays

Verfasst: Mittwoch 27. Februar 2019, 11:47
von phtagen
Hallo liebes Forum,

ich bin noch recht jungfräulich in Python unterwegs. Ich hab bereits im Internet recherchiert in der Annahme mein Problem wäre ein Standardfall in Python, aber irgendwie hab ich mich da geirrt oder bin zu blöd richtig zu suchen.

Folgende Situation: Ich habe eine 2D-Intensitätsverteilung als Messwertmatrix. Man kann sich das wie ein Graustufenbild vorstellen. Ich möchte jetzt allerdings keine Darstellung als Bild, sondern die gemessenen Intensitätswerte als 3D-Scatterplot. D. h. in der MxN-Matrix habe möchte die M-Dimension auf der X-Achse, die N-Dimension auf der Y-Achse und die Intensitätsverteilung als Z-Wert punktweise dargestellt haben (siehe hierzu auch angehängte Grafiken).

Da die Originalmessdaten als Bild vorliegen, habe ich das in ImageJ schon so dargestellt bekommen (siehe intensity_distro für die Originaldaten und wunsch_darstellung für das was ich letztlich erreichen möchte).

Da ich allerdings einfach etwas Freiheit haben möchte, was die Verteilung der Daten auf den Achsen angeht, möchte ich das Ganze in Python umsetzen. Und hier scheitere ich momentan. Ich habe mit plot_surface zumindest schon so was ähnliches hinbekommen (siehe surface_plot_python), allerdings möchte ich hier keine Oberfläche sehen, sondern nur die Datenpunkte selbst.

Hat da jemand eine Idee?

Anhänglich ist noch ein Code-Schnippsel, sowie drei Bilder von dem was ich haben möchte und dem was ich bis jetzt habe. Nebenfrage: Gibt es eine Möglichkeit auf das Meshgrid zu verzichten, sodass ich direkt auf der X-/Y-Achse die Werte aus demX/Y-Array angezeigt bekomme (die Werte entsprechen jeweils einer Länge)? Und wie bekomme ich das Grid aus?

Merci

Phtagen

Code: Alles auswählen

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from skimage import io
data = np.genfromtxt('/path_to_my_data/corr.txt', delimiter = ' ')

X = data[0, 1:]
Y = data[1:, 0]
Z = data[1:, 1:]
nx = data[0,1:].size
ny = data[1:,0].size
npx = np.linspace(0,1,nx)
npy= np.linspace(0,1,ny)
xv, yv = np.meshgrid(npx, npy)

fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')

ax.plot_surface(xv, yv, Z)

ax.set_xlabel('$t_{low}$')
ax.set_ylabel('$t_{hi}$')
ax.set_zlabel('$p_{ges}$')

plt.show()
Bild
Bild
Bild

Re: 3D Scatterplot eines 2D-Arrays

Verfasst: Mittwoch 27. Februar 2019, 12:31
von ThomasL

Re: 3D Scatterplot eines 2D-Arrays

Verfasst: Mittwoch 27. Februar 2019, 13:15
von phtagen
Hallo Thomas,

vielen Dank für deine Antwort. Leider hilft die mir so nicht weiter. Ich habe natürlich bereits Google bemüht und zig ähnliche Seiten mit ähnlichen Beispielen gefunden. Das Problem hierbei ist, dass das Datenarray, welches dort in dem Beispiel geplottet wird, eindimensional ist, denn bei zs handelt es sich um einen Spaltenvektor mit 100 Einträgen.

Ich möchte aber eine Matrix auf diese Weise plotten mit MxN Einträgen.

Ich sehe auch gerade, dass meine Bilder nicht angezeigt werden. Wie kann ich meinen Beitrag editieren um direkt die links anzugeben (ich finde dazu tatsächlich keine Option neben meinem Beitrag?!?)?

Grüße
Pht...

Re: 3D Scatterplot eines 2D-Arrays

Verfasst: Mittwoch 27. Februar 2019, 14:31
von ArtooDetoo
Ich schätze das Stichwort, das du suchst, ist Surface Plot.

edit: Vielleicht doch nicht, es werden ja keine einzelnen Punkte geplottet. Für den von Thomas vorgeschlagenen Scatterplot müsstest du deine Matrix dann in ein eindimensionales Array umwandeln. Dann würde das funktionieren.

Re: 3D Scatterplot eines 2D-Arrays

Verfasst: Mittwoch 27. Februar 2019, 14:59
von phtagen
Hallo ArtooDetoo,

danke für die Antwort. Das mit dem Surface Plot hatte ich auch schon. Aber wie du richtig festgestellt hast, werden da nicht einzelne Punkte geplottet. Bei mir sieht das Ganze im Moment aus wie ein 3D-Bar-Chart.

Gibt es denn irgendwelche Optionen für den Surface Plot, sodass dieser nur als Punktwolke dargestellt wird?

NB: Ich weiß immer noch nicht, wie ich meinen ersten Beitrag editieren kann. Muss das von nem Admin freigeschaltet werden? Egal, hier nochmal die Links zu meinen Bildern, in der Hoffnung, dass die jetzt abrufbar sind.

https://www.bilder-upload.eu/bild-3a078 ... 2.jpg.html
https://www.bilder-upload.eu/bild-1e339 ... 9.jpg.html
https://www.bilder-upload.eu/bild-a7226 ... .jpeg.html

Re: 3D Scatterplot eines 2D-Arrays

Verfasst: Mittwoch 27. Februar 2019, 15:05
von __deets__
Man kann hier Beitraege nur fuer einen gewissen Zeitraum bearbeiten. Danach sind sie gesperrt zur Bearbeitung, damit nicht nachtraeglich Leute Aussagen veraendern oder wie auch so manche Spezis alles loeschen wenn ihr Problem geloest ist - auf das kein anderer was davon hat.

Und hier ist nix dabei? https://matplotlib.org/gallery.html#mplot3d

Re: 3D Scatterplot eines 2D-Arrays

Verfasst: Mittwoch 27. Februar 2019, 15:13
von phtagen
Moin __deets__,

ok gut zu wissen.
damit nicht nachtraeglich Leute Aussagen veraendern oder wie auch so manche Spezis alles loeschen wenn ihr Problem geloest ist
- solche Leute soll es wohl geben...

Auf der von Dir verlinkten Seite war ich auch schon, leider ohne fündig zu werden. Ich hätte ehrlich gesagt nicht gedacht, dass das so ein übler Spezialfall ist, den ich hier haben möchte. Zumal ImageJ genau diese Ansicht von Haus aus mitbringt.

Mhmm, die einzige Idee die ich jetzt noch hätte, wäre über alle Spalten oder Zeilen zu loopen und dann halt jede Spalte/Zeile als Scatter in die Grafik zu hauen.

Aber das kann es doch echt nicht sein, oder?!?

Grüße

Re: 3D Scatterplot eines 2D-Arrays

Verfasst: Mittwoch 27. Februar 2019, 15:16
von __deets__
Also ich verstehe nicht, was zB an https://matplotlib.org/examples/mplot3d ... _demo.html jetzt nicht im Grunde dein gewuenschter Plot ist. Was ist daran falsch? Wenn du die Farbe vom Wert abhaengig machst, bekommst du doch pro Datenpunkt einen Punkt im Plot? Oder verstehe ich nicht, was du willst?

Re: 3D Scatterplot eines 2D-Arrays

Verfasst: Mittwoch 27. Februar 2019, 15:33
von phtagen
Das ist das Beispiel was Thomas mir auch schon vorgeschlagen hatte. Die Argumente die du dem scatter(..) übergibst, müssen alle die gleiche Größe haben. D. h. also, dass das Z-Array nur 1D sein kann. Ich habe ein 2D-Array für Z, d. h. prinzipiell ist hier schon der surface oder contour-plot richtig. Aber die Art der Darstellung passt nicht, ich möchte halt die Daten als Punktwolke dargestellt haben und nicht als Fläche.

Ich habe jetzt mal folgendes gemacht: In einem Loop mache ich aus jeder Zeile meines 2D-Arrays je einen Zeilenvektor und plotte diesen dann mit scatter() in meine Grafik.

Hätte aber nicht gedacht, dass man das so anstellen muss...

Code: Alles auswählen

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from skimage import io

data = np.genfromtxt('/path_to_my_data/corr.txt', delimiter = ' ')

X = data[0, 1:]
Y = data[1:, 0]
Z = data[1:, 1:]
nx = data[0,1:].size

fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')

for i in range(nx):
    ax.scatter(X[:], Y[i], Z[:,i], c='gray', marker='.')

ax.set_xlabel('$t_{low}$')
ax.set_ylabel('$t_{hi}$')
ax.set_zlabel('$p_{ges}$')
ax.grid('off')

plt.show()
Das Ergebnis sieht dann so aus und kommt dem langsam nahe was ich haben möchte:

https://www.bilder-upload.eu/bild-c8edd ... .jpeg.html

Wenn da aber jemand noch einen besseren Vorschlag hat, dann bitte her damit!

Viele Grüße

Pht...