for-Schleife oder ?

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.
Antworten
cwesche
User
Beiträge: 14
Registriert: Mittwoch 10. Februar 2010, 11:43

Hallo zusammen,

nach einer Stunde im Forum und lesen eines Turorials bin ich genauso schlau wie vorher. Folgendes Problem habe ich:
Ich lese eine txt-Datei mit numpy.loadtxt ein. Sie besteht aus 168 Zeilen und 11 Spalten. Zusätzliche habe ich einige Parameter definiert. Nun möchte ich gern einige Berechnungen durchführen.

Code: Alles auswählen

from numpy import *
from pylab import *
from matplotlib import *
from pyproj import Proj
from matplotlib.font_manager import FontProperties
from pylab import *
import glob
import scipy.stats
from itertools import *

file = 'D18_wind_sec.txt'
data = loadtxt(file,skiprows=1)

W=data[:,0]
sec=data[:,1]

#Startkoordinaten
lon_1 = -11.156            
lat_1 = -70.684

#Dimensionen
L = 18000
H = 206

#Transofrmation Geo in UTM
p = Proj(proj='utm',zone=30,ellps='WGS84')
x_1,y_1 = p(lon_1, lat_1)

#Phi
phi = math.radians(lat_1)

#Given parameter:
p_a = 1.29              
p_w = 1027.5            
p_ib = 850.0              

C_aw = 0.0015          
C_w = 0.85              
C_a = 0.4               
C_w2 = 0.1              
omega = 0.0000727       

D = (H*p_ib)/p_w       
S_w = L*D              
S_a = L*(H-D)           
m = p_ib*(L**2*H)  

f =  2*omega*sin(phi)

R = (p_w*C_w*S_w)/2

lamba = (m*f)/(2*R*(1+2*(C_w2)*(L/H)))

##Hier Schleife starten
for i in data:
        tau_aw = p_a*C_aw*W**2
        tau = ((p_a*C_a*S_a)/2)*W**2
        u_e = (-tau_aw)/(p_w*f*D)
        T_star = tau+m*f*u_e
        U_star = sqrt(2*(lamba**2)*(-1+(1+sqrt((T_star**2)/(4*(lamba**2)*(R**2))))))
        u = (u_e-2*lamba*R*(U_star**2))/T_star
        v = (R*(U_star**3))/T_star
        x_2 = x_1+(u*sec)                             #neue UTM Koordinaten
        y_2 = y_1+(v*sec)
        x_1 = x_2                                         #Umbenennen der UTM Koordinaten
        y_1 = y_2
lon_2, lat_2 =p(x_1, y_1, inverse=True)         #Umrechnung der neuen Koordinaten UTM in Geo
print lon_2, lat_2
Ich versuche mich mal an einer Erklärung:
Oberhalb der for-Schleife sind Berechnungen, die ohne wechselnde Werte durchgeführt werden, die Werte bleiben also konstant. Innerhalb der for-Schleife sollen nun Berechnungen mit wechselnden Werten ( W und sec) durchgeführt werden. Dies funktioniert auch, jedoch nicht so, wie ich es mir vorgestellt habe. Ich möchte gern innerhalb der for-Schleife die neuen UTM Koordinaten übergeben (x_1 = x_2 und y_1 = y_2) damit die Änderungen aufsummiert werden und ich final nur eine einzige Koordinate erhalte, die ich dann wieder in geographische umwandle. Irgendwie scheint die Übergabe der Koordinaten nicht zu fuinktionieren, denn ich erhalte als Ausgabe immer wieder einen Array mit allen berechneten Koordinaten - jedoch immer von der obigen Startkoordinate (lon_1, lat_1) ausgehend. Irgendwo habe ich eine Denkfehler bzw. ich bin mir nicht sicher, ob die for-Schleife der richtige Weg ist.

Ich hoffe das war nicht zu verwirrend und ihr könnte mir bei der Lösung helfen.
Grüße
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@cwesche: Wafür ist die for-Schleife gut, wenn Du "i" nirgends benutzt?

Du solltest keine *-importe benutzen. Gerade numpy überschreibt dadurch einige Builtin-Funktionen, so dass man nicht mehr weiß, welche Funktion man tatsächlich benutzt.
BlackJack

@cwesche: Ich vermute Du vermischst hier rechnen mit Einzelwerte und rechnunen mit Numpy-Arrays auf eine Weise die nicht funktioniert. `W` und `sec` sind keine Einzelwerte sondern Arrays. Wenn Du mit denen rechnest, dann rechnest Du immer mit dem kompletten Array. Nach ``x_2 = x_1+(u*sec)`` ist `x_2` zum Beispiel kein skalarer Wert sondern ein Array. Wie sich dessen Inhalt konkret berechnet hängt davon ab ob `u` und `x_1` ihrereseits jeweils Skalar oder Array sind. Eine andere Fehlerquelle könnte sein, dass Du die Vorstellung hast Werte würden bei Zuweisungen kopiert. Das passiert *nicht* Die vier letzten Zeilen in der Schleife sind also sinnfrei. Die letzten beiden kannst Du weglassen und bei den vorletzten beiden `x_1` beziehungsweise `y_1` auf beiden Seiten der Zuweisung schreiben. Das Ergebnis ändert sich dadurch nicht, dass man die *selben* Werten zwischenzeitlich mal an andere Namen gebunden hat.
cwesche
User
Beiträge: 14
Registriert: Mittwoch 10. Februar 2010, 11:43

Hallo zusammen,

danke für die Antworten. Ich habe versucht die Tipps umzusetzen und mit mehreren Tests hat es funktioniert. Nicht zu 100% wie ich mir das vorgestellt habe, aber vermutlich bin ich da etwas naiv an die sache rangegangen. Auf jeden Fall bekomme ich meine finalen Koordinaten wie gewünscht.

Code: Alles auswählen

from numpy import loadtxt
from pyproj import Proj
from matplotlib.font_manager import FontProperties
import glob

file = 'w:/helios2/cwesche/ICEBERG_MODEL/SimpleModel/D18_wind_sec.txt'
data = loadtxt(file,skiprows=1)

W=data[:,0]
sec=data[:,1]

lon_1 = -11.156
lat_1 = -70.684

L = 18000
H = 206

p = Proj(proj='utm',zone=30,ellps='WGS84')
x_1,y_1 = p(lon_1, lat_1)

phi = math.radians(lat_1)

p_a = 1.29              
p_w = 1027.5            
p_ib = 850.0               

C_aw = 0.0015           
C_w = 0.85              
C_a = 0.4              
C_w2 = 0.1             
omega = 0.0000727       

D = (H*p_ib)/p_w        
S_w = L*D               
S_a = L*(H-D)           
m = p_ib*(L**2*H)  

f =  2*omega*sin(phi)

R = (p_w*C_w*S_w)/2

lamba = (m*f)/(2*R*(1+2*(C_w2)*(L/H)))

for i in arange (0,len(data)):
    tau_aw = p_a*C_aw*W[i]**2
    tau = ((p_a*C_a*S_a)/2)*W[i]**2
    u_e = (-tau_aw)/(p_w*f*D)
    T_star = tau+m*f*u_e
    U_star = sqrt(2*(lamba**2)*(-1+(1+sqrt((T_star**2)/(4*(lamba**2)*(R**2))))))
    u = (u_e-2*lamba*R*(U_star**2))/T_star
    v = (R*(U_star**3))/T_star
    x_2 = x_1+(u*sec[i])
    y_2 = y_1+(v*sec[i])
    lon_2, lat_2 =p(x_2, y_2, inverse=True)
    x_1 = x_2
    y_1 = y_2
Grüße
BlackJack

@cwesche: Das ist aber kein besonders guter Code weil es Numpy überhaupt nicht benutzt. Der Witz bei Numpy-Arrays ist ja gerade dass man keine Schleifen in Python verwendet sondern ausnutzt das die Rechenoperationen mit den Arrays schon auf alle Elemente angewendet werden, also die Schleife intern in diesen Objekten in C oder Fortran abläuft.

Auf der anderen Seite ist das auch für reines Python kein guter Code weil das ``for i in range(len(sequence)):`` nur um mit `i` dann auf Elemente der Sequenz zuzugreifen ein „anti pattern” ist. Man erstellt damit eine Liste (oder in diesem Fall ein Array) mit allen ganzen Zahlen von 0 bis ``len(sequence) - 1`` im Speicher. Obwohl man eigentlich nur über die Werte von `sequence` iterieren wollte, was man in Python mit ``for`` *direkt* machen kann. Wenn man parallel über mehrere Sequenzen iterieren möchte gibt es die `zip()`-Funktion beziehungsweise in Python 2 die `itertools.izip()`-Funktion. In dem Fall könnte man die Daten aus der Eingabedatei auch einfach gar nicht erst trennen.

Letztendlich solltest Du aber versuchen Numpy zu nutzen statt Schleifen in Python-Code zu schreiben. Dafür ist das schliesslich gedacht.

`x_2` und `y_2` machen in dem Quelltext immer noch keinen Sinn. Und Du machst mit `lon_2` und `lat_2` überhaupt nichts‽
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@cwesche: wenn ich das richtig sehe, kann man einfach die for-Schleife weglassen und mit Vektoren rechnen:

Code: Alles auswählen

...
tau_aw = p_a*C_aw*W**2
tau = ((p_a*C_a*S_a)/2)*W**2
u_e = (-tau_aw)/(p_w*f*D)
T_star = tau+m*f*u_e
U_star = sqrt(2*(lamba**2)*(-1+(1+sqrt((T_star**2)/(4*(lamba**2)*(R**2))))))
u = (u_e-2*lamba*R*(U_star**2))/T_star
v = (R*(U_star**3))/T_star
x_2 = x_1+(u*sec).sum()
y_2 = y_1+(v*sec).sum()
lon_2, lat_2 =p(x_2, y_2, inverse=True)
cwesche
User
Beiträge: 14
Registriert: Mittwoch 10. Februar 2010, 11:43

Hallo Sirius3,

jup...da kommt genau das raus, was ich mit meiner unständlichen for-Schleife auch herausbekomme. Cool.
Danke dafür!

Hallo BlackJack,

nun was soll ich zu deiner Kritik sagen, vermutlich oder ganz sicher hast du recht, was die Güte des Codes angeht. Ich nutze Python zwar recht viel, aber ich vermute, dass dies auf dem Stand eines absoluten Anfängers ist, der manchmal einfach nur froh ist, dass es funktioniert. Ich werde Besserung geloben und vielleicht mal etwas tiefer in die Materie einsteigen als bisher.
Zu deinen letzten Kritikpunkten, ich sehe diese nicht. x_2 und y_2 hatten ihre Berechtigung, da diese zumindest in meinem Kopf die neue Startposition innerhalb der Schleife dargestellt haben. Vielleicht denk ich da etwas quer oder wir schreiben aneinander vorbei. Den finalen Schritt des Ausgebens in lon_2 und lat_2 habe ich nicht dargestellt, aber das waren quasi die Sachen, die ich berechnet haben wollte. In meinem Skript war die Ausgabe natürlich drin.
Ich denke aber auch dir, dass du mich daraufhingewiesen hast, doch in Zukunft sauberer zu programmeiren.

Grüße
BlackJack

@cwesche: In den Zeilen 52 und 53 bindest Du das Ergebnis von den beiden Rechnungen an `x_2` und `y_2`. Danach machst Du bis zum Schleifenende nichts mehr mit den alten Werten von `x_1` und `y_1`. Du hättest also das Ergebnis der beiden Rechnungen in den Zeilen 52 und 53 auch direkt wieder an `x_1` und `y_1` binden können. Oder um es mal in einfachem Code auszudrücken:

Code: Alles auswählen

    # 
    # Das hier:
    # 
    x = 42
    for _ in range(5):
        x_2 = x * 2
        print x_2
        x = x_2
    # 
    # macht genau das selbe wie:
    # 
    x = 42
    for _ in range(5):
        x = x * 2
        print x
`x_2` ist ein Name der nur die Zuweisung am Ende der ersten Schleife nötig macht, die man sonst weg lassen könnte. Wenn nach der Berechnung nicht sowohl der alte als auch der neue Wert benötigt werden, gibt es keinen Grund den neuen Wert zwischendurch an einen zusätzlichen Namen zu binden.
Antworten