laden von Werten aus binären Dateien schneller machen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
feldmaus
User
Beiträge: 287
Registriert: Donnerstag 12. Oktober 2006, 16:48

So habe jetzt schon mal die Schleife weg:
http://nopaste.debianforum.de/21670

Allerdings muss ich das Einlesen wieder ändern. :shock:

Gesagt getan:
http://nopaste.debianforum.de/21671

Zu Zeile 9 und 10 habe ich da noch eine Frage. Ist es besser erst
ein numpy.array zu deklarieren und dann die Daten mit cPickle zu laden,
oder kann ich gleich die Daten mit cPickle laden ?

Grüße und Danke für Eure Antworten
Zuletzt geändert von feldmaus am Mittwoch 27. Mai 2009, 10:27, insgesamt 1-mal geändert.
feldmaus
User
Beiträge: 287
Registriert: Donnerstag 12. Oktober 2006, 16:48

Hi Alle und Danke nochmal

ich bin in meinem Code auf einen Bug gestoßen und zwar werden meine
vektoren a_p_{1,3} und a_pv_{1,3} manchmal mit unterschiedlich
vielen Elementen gefüllt. Dies führt dann bei den logischen Algorithmen
zu einem Fehler.

Daher wollt ich eine möglichst schnelle Lösung haben um alle
Vektoren immer auf die gleiche Länge zu halten.

Als Beispiel

a_pv_1 = [ -1.87116675e-04 +6.73690811e-05j
-3.73210933e-05 +3.46032903e-05j
-3.82515136e-04 +5.63763548e-04j
-4.02121572e-04 -1.19002536e-04j]

a_pv_2 = [ 0.00015192+0.00012837j
0.00011291+0.00010157j 0.00028497+0.00023856j
0.00012447+0.00010121j]

a_pv_3 = [ 3.51970411e-05 -1.95676592e-04j
9.59062163e-05 -6.19327839e-05j
-1.20625962e-04 -1.87798141e-04j]

Wie man erkennen kann hat mein dritter Vektor weniger Elemente.

In meinem Code werden die Vektoren logisch verknüpft:

Code: Alles auswählen

criterion = (a_p_1==1) | (a_p_2==1) | (a_p_3==1)
Diese Zeile führt zu einem Fehler. Wie kann ich diesen Fehler beseitigen,
und zwar möglichst schnell ?

Grüße Markus
feldmaus
User
Beiträge: 287
Registriert: Donnerstag 12. Oktober 2006, 16:48

Mir ist gerade aufgefallen das die Vektoren a_p_{1,3} das gleiche Problem
aufweisen und es gibt dabei keinen Zusammenhang zwischen den Vektoren
a_pv_{1,3} und a_p_{1,3}. Bzw. der einzigste Zusammenhang ist das es
ein Verhältnis von 8:1 gibt, also die Vektoren a_pv_{1,3} 8 mal länger
sein müssen als a_p_{1,3}.
BlackJack

@feldmann_markus: Das wird wohl daher kommen, dass Du Dateien liest, während ein anderer Prozess Daten anhängt. Dann kann es natürlich passieren, das in ungünstigen Fällen, die Dateien zu dem Zeitpunkt unterschiedliche Anzahlen von Datenpunkten enthalten.

Löungsansatz: Die Datei mit den wenigsten Datenpunkten ermitteln und nur so viele einlesen, bzw. nach dem Einlesen nur die entsprechende Anzahl von Datenpunkten behalten und die überschüssigen wegwerfen.

Oder die sauberere Lösung: Die Architektur überdenken bei der zwei verschiedene Prozesse die gleichen Dateien verwenden.
feldmaus
User
Beiträge: 287
Registriert: Donnerstag 12. Oktober 2006, 16:48

feldmann_markus hat geschrieben:Hi Alle und Danke nochmal

ich bin in meinem Code auf einen Bug gestoßen und zwar werden meine
vektoren a_p_{1,3} und a_pv_{1,3} manchmal mit unterschiedlich
vielen Elementen gefüllt. Dies führt dann bei den logischen Algorithmen
zu einem Fehler.
Ich habe das ganze mal so gelöst,
http://nopaste.debianforum.de/21654

Allerdings ist dies dann immer auf 3 Bänder beschränkt. Hat da jemand
einen guten Vorschlag ?

Grüße Markus
feldmaus
User
Beiträge: 287
Registriert: Donnerstag 12. Oktober 2006, 16:48

BlackJack hat geschrieben:@feldmann_markus: Das wird wohl daher kommen, dass Du Dateien liest, während ein anderer Prozess Daten anhängt. Dann kann es natürlich passieren, das in ungünstigen Fällen, die Dateien zu dem Zeitpunkt unterschiedliche Anzahlen von Datenpunkten enthalten.

Löungsansatz: Die Datei mit den wenigsten Datenpunkten ermitteln und nur so viele einlesen, bzw. nach dem Einlesen nur die entsprechende Anzahl von Datenpunkten behalten und die überschüssigen wegwerfen.

Oder die sauberere Lösung: Die Architektur überdenken bei der zwei verschiedene Prozesse die gleichen Dateien verwenden.
Aber die Vektoren a_p_{1,3} und a_pv_{1,3} werden von Dateien gespeist,
die ja schon vorliegen. Diese Dateien werden nur gelesen, bzw.
während der Analyse nicht beschrieben.

Code: Alles auswählen

        f_p_1 = open('../../../peakdetektor1.hex','rb')
        f_p_2 = open('../../../peakdetektor2.hex','rb')
        f_p_3 = open('../../../peakdetektor3.hex','rb')
        f_pv_1 = open('../../../peakband1.hex','rb')
        f_pv_2 = open('../../../peakband2.hex','rb')
        f_pv_3 = open('../../../peakband3.hex','rb')
        a_p_1 = numpy.fromfile(f_p_1,dtype='b')
        a_p_2 = numpy.fromfile(f_p_2,dtype='b')
        a_p_3 = numpy.fromfile(f_p_3,dtype='b')
        a_pv_1 = numpy.fromfile(f_pv_1,dtype=numpy.complex64)
        a_pv_2 = numpy.fromfile(f_pv_2,dtype=numpy.complex64)
        a_pv_3 = numpy.fromfile(f_pv_3,dtype=numpy.complex64)
Abgesehen davon haben die Dateien unterschiedliche Größen. Mein
Analyse Programm kann da nichts für. Die obigen Dateien werden von
meinem Gnuplot Programm bereit gestellt.

Ist es in Ordnung das die Dateien f_p_{1,3} und f_pv_{1,3} manchmal
mehrere hundert MByte haben ? Also stellt das ein Problem für numpy
dar ?

Grüße Markus
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

vorweg: Es ist immer noch problematisch auf diesen Thread zu antworten*.

Zu den Fragen:
- Kann numpy mit mehreren 100 MB großen Dateien umgehen? - Ja, wenn Dein Rechner genügend RAM hat ... Oder etwas detaillierter: Numpy ist die Verbindung aus dem alten Numeric (eher kurze arrays) und numarray (optimiert für sehr große arrays). Es kann mit beiden umgehen und versucht so performant, wie möglich zu sein.

-
Abgesehen davon haben die Dateien unterschiedliche Größen. Mein
Analyse Programm kann da nichts für. Die obigen Dateien werden von
meinem Gnuplot Programm bereit gestellt.
"Dein Gnuplot-Programm"? Was ist das? Gnuplot ist nicht Dein und wenn Du damit riesige Dateien generierst machst Du was falsch.

- Statt

Code: Alles auswählen

numpy.amin([len(a), len(b)])
geht

Code: Alles auswählen

numpy.min(a.shape, b.shape)[0]
Das spart mehrere Loops. numpy.arrays sind sich Ihrer Größe "bewußt".

- Kommentare würde ich nicht

Code: Alles auswählen

""" so schreiben, denn das sind i.d.R. mehrzeilige
Doc-Strings direkt und der def- oder class-statements"""
# , sonder so, denn das sind einzeilige Kommentare
Und überhaupt solltest Du, wenn Du mal den Kopf frei hast, Dich mit PEP8 auseinandersetzen. Das ist nicht nur Kosmetik: Lesbarerer Code ist auch besser zu warten. (Ach und "shape size" gibt es nicht. Das müsste "not to be of the same shape" heißten ;-) .)

-

Code: Alles auswählen

a_p_1 = numpy.resize(a_p_1,(1,min_p))
a_p_1 = a_p_1[0]
Kannst Du auch in eine Zeile packen:

Code: Alles auswählen

numpy.resize(a_p_1, (min_p,))
Beachte das Komma hinter min_p.

- Wie von BJ schon gesagt: Wenn Du Deine Datenstruktur änderst, machst Du Dir das Leben leichter. Wie wäre

Code: Alles auswählen

{id: [detektor input, band input]}
?
Darüber könntest Du iterieren und Du kannst Dir auf einfach das Festverdrahten der Dateinamen sparen. Und wenn Du weißt welche Länge ein Array bei einer gegebenen Dateigröße hat, kannst Du die Einlese- und Zurechtstutzoperation auch direkt hintereinander weg ausführen - Mein Vorschlag: Dateigrößen ermitteln, min_p errechnen, Daten einlesen und direkt stutzen. Auf diese Weise hälst Du nicht viel mehr als etwa die größte Datein im Speicher - und nicht x mal diese Größe (Overhead durch Python natürlich nicht mitgerechnet).

Hilft das?

Gruß,
Christian
BlackJack

@feldmann_markus: Wenn ich mir die ``print``-Anweisungen so anschaue, denke ich Du solltest mal einen Blick in das `logging`-Modul werfen, oder zumindest eine eigene Funtkion daraus machen.

`min_p` verstehe ich nicht. Warum durch 8 teilen? Zu diesem Zeitpunkt ist das doch ein Array mit `complex64`-Elementen. Das ist als *Bytes* achtmal so gross wie die Arrays mit den Wahrheitswerten, aber die Anzahl der Elemente ist ja nicht von der Bytegrösse abhängig. Ausserdem sollte man zur Sicherheit wohl besser die minimale Anzahl von Elementen über alle sechs Arrays ermitteln.

Das mit dem `resize()` machst Du zu kompliziert. Du machst ein zweidimensionales Array daraus und nimmst davon nur die erste Dimension, statt gleich nur eine Dimension anzulegen, bzw. die Grösse der einzelnen Dimension im Array zu ändern. Ausserdem sollte man das mit der Methode auf dem Array machen können und verhindert so eine Kopie des jeweiligen Arrays. Also:

Code: Alles auswählen

# anstelle von:
        a_p_1 = numpy.resize(a_p_1,(1,min_p)) 
        a_p_1 = a_p_1[0]
# besser:
        a_p_1.resize((min_p,))
Man beachte, dass ich hier die `resize()`-Methode auf dem Array verwende und nicht die `numpy.resize()`-Funktion. Letztere kopiert das Array nämlich, erstere vermeidet das wahrscheinlich.

Man sollte niemals ein "nacktes" ``exept`` ohne konkrete Ausnahmen verwenden. Das behandelt alle Ausnahmen gleich und man sieht keine Ausnahmen mehr, mit denen man nicht gerechnet hat. Zum Beispiel schluckt das einen `NameError` und man bekommt nicht mit, wenn man sich bei einem Namen vertippt. Solche Fehler sind dann nur sehr mühsam zu finden.

Da es Dir auf Geschwindigkeit ankommt, ist es auch ziemlich ungünstig die kompletten alten Daten zu den neuen in den Speicher zu lesen, nur um festzustellen, ob die neuen Daten mehr enthalten als die alten. Und auch das erneute Schreiben der Daten, die man ja zum Grossteil schon einmal geschrieben hat, kostet unnötig Zeit. Es wäre günstiger sich ein Datenformat zum Speichern zu wählen, bei dem man ohne die Daten komplett einzulesen, ermitteln kann wieviele Datenpunkte schon gespeichert sind, dann aus den Messdaten nur den Ausschnitt mit neuen Daten zu lesen, und die dann an die alten Daten anzuhängen. Eine Datenbank würde sich da zum Beispiel anbieten. SQLite ist relativ unkompliziert zu verwenden, oder vielleicht bietet sich hier auch eine hdf5-Datenbank an. Die Python-Anbindung an letztere heisst `PyTables`.

Quelltextwiederholungen sollte man vermeiden. Nach dem ``except`` steht noch mal das gleiche wie im ``else``-Teil innerhalb des ``try``-Blocks dafür. Wenn man da jetzt Änderungen vornimmt, muss man immer daran denken, die an beiden Stellen exakt gleich zu machen. Das ist eine unnötige Fehlerquelle.

Für eine beliebige Anzahl von Bändern kann man Listen mit den Arrays verwenden. Wenn man Namen durchnummeriert, ist das sowieso oft ein Zeichen dafür, dass man besser eine Liste verwenden sollte.

Das ich diese ganzen Bänder-Daten in einer Klasse kapseln würde, erwähnte ich schon einmal, oder? ;-)
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Oh, ja das mit dem logging-Modul wollte ich auch vorgeschlagen haben. Und PyTables ist eine gute Idee!
Und ja, eigentlich wäre eine Bänder-Klasse einfacher zu handhaben, als mein Strukturvorschlag.

Aber Vorsicht:

Code: Alles auswählen

a.resize(shape tuple)
geht nur, wenn das array nichts referenziert, bzw. nicht referenziert wird. Das ist also ein Ausdruck der in einem Loop nicht zu verwenden ist, da ja kurzeitig referenziert würde. Ansonsten aber, da hast Du, BlackJack, recht, ist der Ausdruck zu bevorzugen.

Gruß,
Christian
feldmaus
User
Beiträge: 287
Registriert: Donnerstag 12. Oktober 2006, 16:48

CM hat geschrieben:
Abgesehen davon haben die Dateien unterschiedliche Größen. Mein
Analyse Programm kann da nichts für. Die obigen Dateien werden von
meinem Gnuplot Programm bereit gestellt.
"Dein Gnuplot-Programm"? Was ist das? Gnuplot ist nicht Dein und wenn Du damit riesige Dateien generierst machst Du was falsch.
Ich meinte nicht Gnuplot sondern Gnuradio. Ist eine Software zum
steuern und auswerten von einem USB Peripherie Sende und Empfangs-
Gerät.
CM hat geschrieben:- Wie von BJ schon gesagt: Wenn Du Deine Datenstruktur änderst, machst Du Dir das Leben leichter. Wie wäre

Code: Alles auswählen

{id: [detektor input, band input]}
?
Den Grundstein dafür habe ich schon gelegt, da ich in beim anlegen
der binären Dateien folgendes logge:

Code: Alles auswählen

starttime = time.time()
f_daten = file('../../../peakdaten.dat','w')
cPickle.dump([starttime, samp_rate,
[datei1_mit_peaks,datei2_mit_peaks,datei3_mit_peaks],
[datei1_mit_peakWerte,datei2_mit_peakWerte,datei3_mit_peakWerte]],
f_daten)
f_daten.close()
endtime = time.time()
f_daten = file('../../../peakdaten.dat','a')
cPickle.dump([endtime], f_daten)
Allerdings habe ich mein Programm noch nicht dynamisch umgeändert.
Wie kann man dynamisch Variablennamen erzeugen ?

Zur Zeit habe ich ja feste Variablennamen für a_p_{1,3} u.s.w..
Mein Analyse Programm muss ja für die gespeicherten
datei{x}_mit_peakWert und datei{x}_mit_peaks Variablen
Namen dynamisch erzeugen:

Code: Alles auswählen

filetmp = open('../../../peakdaten.dat')
datenliste = cPickle.load(filetmp)
starttime = datenliste[0]
samp_rate = datenliste[1]
for peaks in datenliste[2]:
      #deklariere Variablennamen

for peakWerte in datenliste[3]:
      #deklariere Variablennamen
Grüße Markus
BlackJack

@feldmann_markus: Du willst keine Namen dynamisch erzeugen, du willst einfach die Liste verwenden und der einen "statischen" Namen geben.

Code: Alles auswählen

peaks = datenliste[2]
# ...
criterion = (peaks[0] | peaks[1] | peaks[2]).astype(numpy.bool8)
Oder letzteres besser unabhängig von der Anzahl der Bänder:

Code: Alles auswählen

criterion = numpy.bitwise_or.reduce(peaks).astype(numpy.bool8)
feldmaus
User
Beiträge: 287
Registriert: Donnerstag 12. Oktober 2006, 16:48

BlackJack hat geschrieben:@feldmann_markus: Wenn ich mir die ``print``-Anweisungen so anschaue, denke ich Du solltest mal einen Blick in das `logging`-Modul werfen, oder zumindest eine eigene Funtkion daraus machen.
Hört sich interessant an. Gleich mal merken.
BlackJack hat geschrieben:`min_p` verstehe ich nicht. Warum durch 8 teilen? Zu diesem Zeitpunkt ist das doch ein Array mit `complex64`-Elementen. Das ist als *Bytes* achtmal so gross wie die Arrays mit den Wahrheitswerten, aber die Anzahl der Elemente ist ja nicht von der Bytegrösse abhängig. Ausserdem sollte man zur Sicherheit wohl besser die minimale Anzahl von Elementen über alle sechs Arrays ermitteln.
Mein Fehler. Man muss nicht durch 8 teilen. Du hast recht.
Wird geändert. Und Minium über alle 6 Dateien ermitteln.
BlackJack hat geschrieben:Das mit dem `resize()` machst Du zu kompliziert. ...

Code: Alles auswählen

# anstelle von:
        a_p_1 = numpy.resize(a_p_1,(1,min_p)) 
        a_p_1 = a_p_1[0]
# besser:
        a_p_1.resize((min_p,))
Geändert.
BlackJack hat geschrieben:Man sollte niemals ein "nacktes" ``exept`` ohne konkrete Ausnahmen verwenden.
Vorgemerkt für eventuelle Änderung.
BlackJack hat geschrieben:Da es Dir auf Geschwindigkeit ankommt, ist es auch ziemlich ungünstig die kompletten alten Daten zu den neuen in den Speicher zu lesen, nur um festzustellen, ob die neuen Daten mehr enthalten als die alten.
im Prinzip wollte ich damit nur erreichen, das die Daten NICHT bei jedem
Programm Start neu geschrieben werden, wegen der Performance.
Die binären Dateien ändern sich ja nur wenn ich mein Gnuradio
Programm laufen lasse.
Ich könnte auch die ersten 100 Datensätze vergleichen, dass würde
schneller gehen.
BlackJack hat geschrieben:Quelltextwiederholungen sollte man vermeiden. Nach dem ``except`` steht noch mal das gleiche wie im ``else``-Teil innerhalb des ``try``-Blocks dafür.
Vorgemerkt zur Änderung.

Grüße und Danke für Eure Antworten Markus
feldmaus
User
Beiträge: 287
Registriert: Donnerstag 12. Oktober 2006, 16:48

BlackJack hat geschrieben:@feldmann_markus: ...
Oder letzteres besser unabhängig von der Anzahl der Bänder:

Code: Alles auswählen

criterion = numpy.bitwise_or.reduce(peaks).astype(numpy.bool8)
Das gefällt mir. Vorgemerkt zur Änderung.

Ich habe allerdings immer noch ein Problem mit dem "criterion". Irgendwie
wird das "criterion" auf mein Vektoren a_time, a_p_{1,3} und a_pv_{1,3}
falsch angewendet:
http://nopaste.debianforum.de/21672

mein print Anweisungen in dem obigen Code erzeugen:
a_time ist [ 0.00000000e+00 3.01154705e-06 6.02309410e-06 ..., 3.21740265e+01
3.21740303e+01 3.21740341e+01]

len(a_time[criterion]) ist 2

a_time[criterion] ist [ 3.01154705e-06 1.20461882e-05]

a_p_1 ist [0 1 0 ..., 0 0 0]

len(a_p_1[criterion]) ist 2

a_p_1[criterion] ist [1 1]

a_pv_1 ist [ 4.76837158e-07 -7.15255737e-07j -1.80000000e+01 -2.60000000e+01j
2.38418579e-07 -3.10000000e+01j ..., 1.10000000e+01 +2.60000000e+01j
-3.00000000e+01 -1.99999976e+00j 1.39999990e+01 -2.50000000e+01j]

len(a_pv_1[criterion]) ist 2

a_pv_1[criterion] ist [-18.-26.j 26.-13.99999905j]
Habt Ihr eine Idee was ich falsch mache ?

Grüße Markus
feldmaus
User
Beiträge: 287
Registriert: Donnerstag 12. Oktober 2006, 16:48

Ich habe mich geirrt, es scheint doch nur 2 mal die 1 in den Dateien
peakdetektor{1,3}.hex vorhanden zu sein, aber die Zurdnung stimmt nicht.
peakband1.hex enthält(Die ersten 5 * 64 bit):
4.768372E-07 -7.152557E-07j
-1.800000E+01 -2.600000E+01j
2.384186E-07 -3.100000E+01j
1.400000E+01 -2.600000E+01j
2.600000E+01 -1.400000E+01j

Und meine peakdetektor1.hex enthält(Die ersten 5 * 8 bit):
00
01
00
00
01

Wie man aber in meinem print Ausrücken erkennen kann:
a_pv_1[criterion] ist [-18.-26.j 26.-13.99999905j]
:-) bin ich nicht ganz bei der Sache. :lol:
Also scheint doch zu stimmen mit "criterion" und der Zurdnung.

Komischerweise hat meine Gnuradio Software bei dem 5. complexen 64
bit Wert einen Peak gefunden, aber beim 4. nicht, aber dafür kann mein Analyse Programm nichts.

Grüße Markus
feldmaus
User
Beiträge: 287
Registriert: Donnerstag 12. Oktober 2006, 16:48

Es wird mal wieder Zeit für ein paar Quiz Fragen, :-)

in meiner Methode extrahierePeaks() habe ich jetzt versucht die fixe
Anzahl von Bändern zu beseitigen. Bis jetzt bin ich bis Zeile 18,
http://pastebin.com/m31cbae1c
Dort mache ich dann:

Code: Alles auswählen

for array_peakvalue in array_peakvalues:
            array_peakvalue.resize((upper_limit,))
Dabei ist array_peaks eine Liste mit 3 Peak Vektoren und
array_peakvalues ist die Liste mit meinen 3 Peak Werte Vektoren.
Als Fehler bekomme ich,
ValueError: cannot resize an array that has been referenced or is referencing
another array in this way. Use the resize function
Die Fehlermeldung verstehe ich zwar, aber wie kann ich trotzdem Arrays
in einer Liste stutzen ?
Hat jemand ne andere Idee ?

Grüße Markus
feldmaus
User
Beiträge: 287
Registriert: Donnerstag 12. Oktober 2006, 16:48

feldmann_markus hat geschrieben:Hat jemand ne andere Idee ?
Ok habe es so gelöst:

Code: Alles auswählen

        for i in np.arange(len(array_peaks)):
            array_peaks[i].resize((upper_limit,))
        for i in np.arange(len(array_peakvalues)):
            array_peakvalues[i].resize((upper_limit,))
BlackJack

@feldmann_markus: Da ist für meinen Geschmack immer noch einiges zu umständlich.

Zum Beispiel das "Muster" mit dem Du Listen erzeugst, mit dem Anlegen einer leeren Liste gefolgt von einer Schleife, die diese Liste dann befüllt, kann man in vielen Fällen durch kompaktere Konstrukte ersetzen, wie "list comprehension" oder auch mit `map()`. Das ``liste += [ein_element]`` ist auf jeden Fall ein "Antipattern". ``+=`` erweitert die `liste` um alle Elemente in dem Objekt auf der rechten Seite. Da ist ja aber nur *ein* Element drin, d.h. Du erzeugst für jedes Element unnötigerweise eine Liste wo nur dieses eine Element drin steckt. Zum Hinzufügen eines einzelnen Elements ist die `append()`-Methode da.

Auch muss man nicht alles aus `numpy` nehmen, wenn es Funktionen in der Grundausstattung gibt, die das gleiche leisten, oder zumindest genug leisten. `numpy.amin()` ist toll für mehrdimensionale Arrays, weil man die Achse angeben kann, über die das Minimum ermittelt wird, aber für eine einfache Python-Liste reicht das normale `min()` völlig aus. Ähnliches gilt für `numpy.arange()` um Integer-Indizes für eine Schleife zu erzeugen. Damit erzeugt man ein Array mit der entsprechenden Anzahl von Zahlen im Speicher, dass man aber nie in seiner ganzen Grösse benötigt, sondern immer nur eine Zahl davon pro Schleifendurchlauf. Das ist ein Job für `xrange()`.

Die Punkte in den letzten beiden Absätzen sind natürlich beim vorliegenden Quelltext nicht so wild, weil es insgesamt nur um 6 Elemente geht, aber man sollte sich bewusst sein, dass das nicht unbedingt gut skaliert.

Vorschlag für die Zeilen 14 bis 21:

Code: Alles auswählen

        all_arrays = array_peaks + array_peakvalues
        upper_limit = min(map(len, all_arrays))
        for i in xrange(len(all_arrays)):
            all_arrays[i].resize((upper_limit,))
Hat das "gnuradio"-Programm die Dateien eigentlich noch offen, wenn Du sie ausliest?
feldmaus
User
Beiträge: 287
Registriert: Donnerstag 12. Oktober 2006, 16:48

Danke für deine Antwort,

ich habe mal mit list comprehension gearbeitet und die Zeile 3 bis 8
geändert.
http://pastebin.com/m60bd9ef3
Ich bekomme dann die Fehlermeldung:
File "./histogramm.py", line 78, in extrahierePeaks
list_allarrays.resize((upper_limit,))
ValueError: cannot resize an array that has been referenced or is referencing
another array in this way. Use the resize function

Ich nehme mal an das liegt daran, dass ich meine Peak und Peak-Werte
Vektoren in einer Liste referenziere und diese Liste wieder referenziere ?
Zuletzt geändert von feldmaus am Donnerstag 28. Mai 2009, 09:59, insgesamt 2-mal geändert.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

Ja, und wenn Du der Fehlermeldung, BlackJack und nicht glaubst:

Code: Alles auswählen

>>> from numpy import arange
>>> a = arange(10)
>>> help(a.resize)
;-)
Mögliche Lösungen hat BlackJack bereits beschrieben.

Gruß,
Christian
BlackJack

@feldmann_markus: Das ist ja krass:

Code: Alles auswählen

In [150]: a = numpy.arange(10)

In [151]: a.resize((5,))

In [152]: a = numpy.arange(10)

In [153]: b = a

In [154]: a.resize((5,))
---------------------------------------------------------------------------
<type 'exceptions.ValueError'>            Traceback (most recent call last)

/home/bj/<ipython console> in <module>()

<type 'exceptions.ValueError'>: cannot resize an array that has been referenced or is referencing
another array in this way.  Use the resize function
Damit ist die `resize()`-Methode ja nahezu nutzlos. Wer sich das ausgedacht hat, gehört geschlagen.

Aaah, man kann die Überprüfung verhindern:

Code: Alles auswählen

In [155]: a.resize?
Type:           builtin_function_or_method
Base Class:     <type 'builtin_function_or_method'>
String Form:    <built-in method resize of numpy.ndarray object at 0x85d4200>
Namespace:      Interactive
Docstring:
    a.resize(new_shape, refcheck=True, order=False) -> None. Change array shape.

    Change size and shape of self inplace.  Array must own its own memory and
    not be referenced by other arrays.    Returns None.


In [156]: a.resize((5,), refcheck=False)

In [157]: a
Out[157]: array([0, 1, 2, 3, 4])

In [158]: b
Out[158]: array([0, 1, 2, 3, 4])
Ansonsten sind die "list comprehension"s, die Du da jetzt verwendest natürlich völlig fehl am Platze. ;-)

Sorry, aber man muss natürlich nicht alle Schleifen durch LCs ersetzen. Die Ausführungsreihenfolge ist ja jetzt total umgestellt. Statt nacheinander für jede Datei drei Arbeitsschritte durchzuführen, werden die Schritte nun nacheinander aber für jede Datei gemacht. Dabei werden mehr Zwischenergebnisse im Speicher gehalten. Zusammen mit der Indexerei um jeweils nur auf die Hälfte der offenen Dateien zuzugreifen ist das jetzt schwerer verständlich als vorher.

Mit ``is`` darf man nur auf Objektidentität testen, nicht auf Gleichheit. Und es ist nicht garantiert, dass es nur ein `True`-Objekt gibt. Zumal man sich dort einen expliziten Vergleich sowieso sparen kann, denn `data_shall_be_saved` *ist* ja schon ein Wahrheitswert, den braucht man nicht noch einmal mit einem Wahrheitswert vergleichen, wo bei dem Vergleich dann sowieso wieder der gleiche Wahrheitswert herauskommt.

Ich hätte fast bemängelt, dass die Datendateien nicht wieder geschlossen werden, als ich ziemlich weit unten die Schleife entdeckte. Warum erst dort? Und warum über einen Index auf die Elemente zugreifen?

Der Name des Objekttyps sollte übrigens nicht im Namen auftauchen, an den das Objekt gebunden wird. Wenn man den Typ mal ändern sollte, was bei dynamischen Sprachen gar nicht so selten passiert, stimmen die Namen plötzlich nicht mehr und vermitteln dem Leser falsche Vorstellungen über die Eigenschaften des Objekts.
Antworten