Numpy abstrahiert den Unterschied zwischen Fortran-Ordnung und C-Ordnung auf der Python-Ebene. (Tatsächlich können Sie sogar andere Ordnungen für & gt; 2d-Arrays mit numpy haben. Sie werden alle auf der Python-Ebene gleich behandelt.)
Das einzige Mal, wenn Sie sich über die C-zu-F-Sortierung Gedanken machen müssen, ist das Lesen / Schreiben auf die Festplatte oder das Übergeben des Arrays an Funktionen auf niedrigerer Ebene.
Ein einfaches Beispiel
Lassen Sie uns als Beispiel ein einfaches 3D-Array in C-Reihenfolge und Fortran-Reihenfolge erstellen:
%Vor% Beachten Sie, dass beide identisch aussehen (sie sind auf der Ebene, mit der wir interagieren). Wie können Sie feststellen, dass sie in verschiedenen Ordnungen sind? Werfen wir zuerst einen Blick auf die Flaggen (achten Sie auf C_CONTIGUOUS
vs F_CONTIGUOUS
):
Und wenn Sie den Flags nicht vertrauen, können Sie die Speicherreihenfolge effektiv anzeigen, indem Sie arr.ravel(order='K')
betrachten. Die order='K'
ist wichtig. Andernfalls wird beim Aufruf von arr.ravel()
unabhängig vom Speicherlayout des Arrays die Ausgabe in C-Reihenfolge angezeigt. order='K'
verwendet das Speicherlayout.
Die Differenz wird tatsächlich in strides
des Arrays dargestellt (und gespeichert). Beachten Sie, dass c_order
's strides (72, 24, 8)
sind, während f_order
' s strides (8, 24, 72)
sind.
Nur um zu beweisen, dass die Indexierung genauso funktioniert:
%Vor%Lesen und Schreiben
Der Hauptort, an dem Sie Probleme damit bekommen, ist, wenn Sie von der Festplatte lesen oder auf die Festplatte schreiben. Viele Dateiformate erwarten eine bestimmte Reihenfolge. Ich vermute, dass Sie mit seismischen Datenformaten arbeiten, und die meisten von ihnen (z. B. Geoprobe .vol, und ich denke Petrels Volumenformat) schreiben im Wesentlichen einen binären Header und dann ein Fortran-geordnetes 3D-Array auf die Festplatte / p>
In diesem Sinne benutze ich als Beispiel einen kleinen seismischen Würfel (Auszug einiger Daten aus meiner Dissertation).
Bei beiden handelt es sich um binäre Arrays von uint8
s mit einer Form von 50x100x198. Einer ist in C-Reihenfolge, während der andere in Fortran-Reihenfolge ist. c_order.dat f_order.dat
Um sie zu lesen:
%Vor% Beachten Sie, dass der einzige Unterschied darin besteht, das Speicherlayout für reshape
anzugeben. Das Speicherlayout der beiden Arrays ist immer noch anders (Neugestaltung erstellt keine Kopie), aber sie werden identisch auf der Python-Ebene behandelt.
Nur um zu beweisen, dass die Dateien wirklich in einer anderen Reihenfolge geschrieben sind:
%Vor%Lassen Sie uns das Ergebnis visualisieren:
%Vor%
Beachten Sie, dass wir sie auf die gleiche Weise indiziert haben, und sie werden identisch angezeigt.
Häufige Fehler mit IO
Als Erstes sollten wir versuchen, die Fortran-geordnete Datei so zu lesen, als ob sie C-geordnet wäre, und dann das Ergebnis betrachten (indem wir die Funktion plot
oben verwenden):
Nicht so gut!
Sie haben erwähnt, dass Sie "umgekehrte" Indices verwenden müssen. Dies liegt wahrscheinlich daran, dass Sie das, was in der obigen Abbildung passiert ist, behoben haben, indem Sie etwas wie (beachten Sie die umgekehrte Form!) Gemacht haben:
%Vor%Stellen wir uns vor, was passiert:
%Vor%
Beachten Sie, dass das Bild ganz rechts (das Zeitfenster) des ersten Plots mit einer transponierten Version des Bildes ganz links neben dem zweiten Plot übereinstimmt.
Gleichermaßen ergeben print rev_f_order[1,2,3]
und print c_order[3,2,1]
beide 140
, während die Indexierung auf die gleiche Weise zu einem anderen Ergebnis führt.
Hier kommen im Grunde Ihre umgekehrten Indizes her. Numpy denkt, dass es sich um ein C-geordnetes Array mit einer anderen Form handelt. Beachten Sie, wenn wir die Flags betrachten, sind sie beide C-zusammenhängend im Speicher:
%Vor%Dies liegt daran, dass ein Fortran-geordnetes Array einem C-geordneten Array mit der umgekehrten Form entspricht.
Schreiben auf Festplatte in Fortran-Order
Es gibt eine zusätzliche Falte beim Schreiben eines numpigen Arrays auf Festplatte in Fortran-Reihenfolge.
Wenn Sie nichts anderes angeben, wird das Array unabhängig vom Speicherlayout in C-Reihenfolge geschrieben! (In der Dokumentation zu ndarray.tofile
gibt es eine klare Anmerkung, aber es ist ein gewöhnlicher Fehler. Das umgekehrte Verhalten wäre jedoch falsch, i.m.o.)
Daher müssen Sie, ungeachtet des Speicherlayouts eines Arrays, um es in Fortran-Reihenfolge auf Festplatte zu schreiben:
%Vor% Wenn Sie es als ASCII schreiben, gilt das Gleiche. Verwende ravel(order='F')
und schreibe dann das 1-dimensionale Ergebnis heraus.