Seite 1 von 1

So eine Art Switch einbauen

Verfasst: Freitag 11. Februar 2011, 00:07
von mzh
Liebe Leute
Ich hab mir folgendes Skript gebastelt, dass ein GNUPlot File erstellt in welchem eine Cosinus Funktion überlagert wird. Der Hintergrund ist, dass so ein Wellenpaket modelliert werden kann.

Code: Alles auswählen

#!/usr/bin/env python3

# NOTE:
# - Write superpositions of wavefunction into a
#   plotting script
# - The wavefunction is a linear combination according to
#    psi(x) = sum[ (1/N)*cos(k*pi*x), k=1..N]

import os  

# The primitive wavefunction
def wave(N, k): 
    return '1/{0}.0*cos({1}.0*pi*x)'.format(N,k)

# Superimposing the wavefunction
def loop(L):
    function = ''
    for i in range(1, L+1):
        if i < L:
            function += wave(L, i) + '+' 
        else:
            function += wave(L, i)
    return '(' + function + ')*(' + function + ')', L

# Generating the GNUPlot script
def writeGnuString(functions, lw='2'): 
    gs  = ''
    gs += 'set xrange[-1:1]\n'
    gs += 'plot \\' + '\n'
    i = 0 
    for func in functions: 
        if i < len(functions)-1:
            gs += '{0} title "N={1}" lw {2}, \\'\
                    .format(func[0], func[1], lw) + '\n'
            i+=1
        else:
            gs += '{0} title "N={1}" lw {2};\n'\
                    .format(func[0], func[1], lw) 
    gs += 'pause -1;'
    return gs

# Work
functions = []

# Number of superpositions
for i in [2,5,10,25]:
    functions.append(loop(i))

file = open('wave.gnu', 'w')
file.write(writeGnuString(functions))
file.close()

os.system('gnuplot wave.gnu')
Wenn GNUPlot auf dem System installiert ist, wird das Programm ausgeführt und erst nach Drücken der Eingabetaste wird es beendet. Die 'wave' Funktion liefert die primitive Wellenfunktion und in der 'loop' Funktion wird daraus 'wave^2'. Was ich nun wissen möchte ist, wie kann ich am besten einen Switch einbauen, so dass ich mit einem Parameter bestimmen kann, ob mir 'wave' oder 'wave^2' ins GNUPlot Skript geschrieben wird (der Unterschied ist ja dass 'wave^2' nicht negative wäre und somit physikalische Signifikanz erlangt). Natürlich dachte ich mir, ich kann sowas wie einen Kondition einbauen, if param=='sqr': return wave*wave else: return wave. Kann man das nicht schlauer machen?
Weiter bin ich auch offen für Hinweise zur sinnvollen Optimierung des Codes hinsichtlich den Formatting Konventionen, list comprehensions, lambda functions etc etc.
Freue mich auf Beiträge.

Re: So eine Art Switch einbauen

Verfasst: Freitag 11. Februar 2011, 00:28
von cofi
Hier erstmal die ueberarbeitete Version: http://paste.pocoo.org/show/336146/

Da gibt es so einige Varianten, nur kann man das schlecht anhand deiner Informationen abwaegen. Wenn sich an der Funktion nicht mehr viel aendern soll, wuerde ich zu der einfachen `if`-Abfrage raten, auch moeglich ist eine eigene Funktion, etc etc.

Re: So eine Art Switch einbauen

Verfasst: Freitag 11. Februar 2011, 00:59
von BlackJack
`loop()` liesse sich wohl auch so schreiben:

Code: Alles auswählen

def loop(L):
    """Superimposing the wavefunction"""
    function = '+'.join(wave(L, i) for i in range(1, L + 1))
    return '({0})*({0})'.format(function), L
Aber kann man das Quadrat in GNUPlot nicht auch anders ausdrücken als tatsächlich den Ausdruck zweimal zu "schreiben"? Gibt's da nicht '^2' oder '**2' oder eine `pow()`-Funktion?

Re: So eine Art Switch einbauen

Verfasst: Freitag 11. Februar 2011, 09:30
von mzh
@blackjack: ich hab da nicht lange drüber nachgedacht. Ziemlich sicher schon.
Vielen Dank für die Hinweise soweit.

Re: So eine Art Switch einbauen

Verfasst: Freitag 11. Februar 2011, 09:41
von Xynon1
Also laut http://www.gnuplot.info/docs_4.4/gnuplot.pdf 13.2.2 binary Operators, sollte ** durchaus möglich sein.

Re: So eine Art Switch einbauen

Verfasst: Freitag 11. Februar 2011, 14:22
von mzh
stimmt. Danke für den Link.
Mir ist da aber gerade eine andere Frage in den Sinn bekommen. Ich hab ja hier die 'format()' Syntax benutzt um Strings zu erstellen.
Ist es möglich, den Code so zu schreiben, dass das Skript auch noch mit Python 2.x kompatibel bleibt, wo es ja noch keine '.format()' Methode gibt?

Vielen Dank für weitere Hinweise.

Re: So eine Art Switch einbauen

Verfasst: Freitag 11. Februar 2011, 14:31
von BlackJack
@mzh: Naja statt `format()` dann halt den ``%``-Operator.

Code: Alles auswählen

def wave(N, k):
    """The primitive wavefunction"""
    return '1/%s.0*cos(%s.0*pi*x)' % (N, k)


def loop(L):
    """Superimposing the wavefunction"""
    function = '+'.join(wave(L, i) for i in range(1, L + 1))
    return '(%s)*(%s)' % (function, function), L

Re: So eine Art Switch einbauen

Verfasst: Freitag 11. Februar 2011, 14:57
von mzh
Ja, so ists schon möglich. Aber war es nicht so, dass der Trend in die Richtung geht, den '%' Operator nicht mehr einzusetzen? Andererseits, ist es nicht so, dass sich hier die Möglichkeit auftun würde einen Callback zu verwenden? Dh., wenn ich das richtig verstanden habe, die Funktion wird für Python 2 und Python 3 geschrieben, an einen Bezeichner gebunden, aber erst beim Aufruf wird entschieden, welche Version nun ausgeführt wird. Muss da ein bisschen mehr darüber nachlesen, bin aber ganz sicher dass ich es irgendwo sah.

Re: So eine Art Switch einbauen

Verfasst: Freitag 11. Februar 2011, 15:15
von cofi
Ja natuerlich geht das. Nur ist es so, dass `%` von beiden Versionen unterstuetzt wird und in Python 3 auch nicht irgendwann wegfallen wird. Insofern kann man sich da die Arbeit sparen.

Re: So eine Art Switch einbauen

Verfasst: Freitag 11. Februar 2011, 15:57
von BlackJack
@mzh: Wenn es kein `str.format()` gibt, kann man schlecht von ``%`` weg kommen. Das mit dem Callback habe ich jetzt nicht verstanden!?

Re: So eine Art Switch einbauen

Verfasst: Freitag 11. Februar 2011, 17:41
von mzh
BlackJack hat geschrieben:@mzh: Wenn es kein `str.format()` gibt, kann man schlecht von ``%`` weg kommen. Das mit dem Callback habe ich jetzt nicht verstanden!?
komme darauf zurück.