Seite 1 von 1

Parameter an Funktionen uebergeben

Verfasst: Montag 19. August 2013, 22:11
von peter99
Ich bin dabei meinen code zu vereinfachen und dabei wieder auf ein Problem gestossen. Mittlerweile habe ich Funktionen in meiner main-Funktion, die nicht eigens in der main-Funktion aufgerufen werden, sondern von anderen Parametern abhaengen. Jetzt will ich aber von einer dieser Funktionen Parameter an eine andere Funktion uebergeben.. um nicht nochmal eine Rechnung durchfuehren zu muessen.
Hier mein Problem:
weil compute_field keine Funktion ist, die eigens in main aufgerufen wird, kann ich info_for_click nicht uebergeben...
zuvor habe ich die rechnung in der anderen Funktion nochmal durchgefuehrt, was ziemlich bescheuert ist, aber ich weiss nicht, wie ich es sonst umgehen soll...

Code: Alles auswählen

from math import*
from string import*
table = display.getWidget("Table").getTable()
table1 = display.getWidget("Table1").getTable()
c0 = 299792458.0
betaS = 0.041
geff = 0.067539767
#big letter because lambda seems to be predefined
Lambda = 3.724129913
# should help not to use not defined functions until this moment
k = 2
s = 2
Vebit0 = 1
# find a better solution
Qout = []
numberout = []
Energyout = []
fieldout = []

def main():
    Qcont, A1, Around, nameiso, abu, qdivbya, abu2, information = readcontaminationfile()
    cavmaxCSS, cavmaxreal, factor = readcavmaxfile()
    phi, Qin, A, E, diffE, minimumf, maximumf, Vebitmax, check2, check1, check3, check4, checks,\
           number, numbers, diffqa0, cavlist, combo = getInputs(A1, Around, nameiso, Qcont, factor)
    alarm(cavlist, cavmaxCSS, number)
    decision(phi, Qin, A, E, diffE, minimumf, maximumf, Vebitmax, checks, \
             number, numbers, cavlist, factor, cavmaxCSS, cavmaxreal)
    clickrow(Qcont, A1, nameiso, abu, qdivbya, abu2, information, A, diffqa0, check3, check4, factor, \
             phi, minimumf, maximumf, cavmaxreal, combo)

def refresh():        
    table.setContent([[" ", " ", " ", " "]])
    table1.setContent([[" ", " ", " ", " ", " ", " "]])


...
...
...

def alarm(cavlist, cavmaxCSS, number):
    for i in range(1, number + 1):
        if number >= i and cavlist[i-1] > cavmaxCSS[i-1]:
            display.getWidget("cav" + str(i)).setPropertyValue("foreground_color",RED)


def compute_field(s, A, phi,  k, Vebit0, Vebitmax, cavmaxreal, factor, betaS, minimumf, maximumf, diffE, E):
    E_average = (600 + E)/2
    v_averge = sqrt(2*E_average*1.602177*10**(-16)/1.6726*10**27)
    beta_average = v_averge/c0
    tmp = pi * geff / (beta_average * Lambda)
    T_average = sin(tmp)/tmp*sin(pi*betaS/(2*beta_average))
    fieldreal = diffE*A/(27.98*k*float(s)*T_average*cos(phi))
    listfields = [fieldreal]* int(s)
    # cannot be defined earlier because otherwise listfields not already defined
    condition_field = (
    all(fieldreal > minimumf and fieldreal < maximumf and t < u for t, u in zip(listfields, cavmaxreal)) and Vebit0 < Vebitmax
    )
    if condition_field:
        Qout.append(k)
        fieldout.append(fieldreal)
        numberout.append(s)
        Energyout.append(E)
        set_cells(table, len(Qout) - 1, k, Vebit0, s, E)
    # no provide information for click
    info_for_click = zip(Qout, fieldout, numberout, Energyout)
   # else:
      #  refresh()
    return info_for_click


def decision(phi, Qin, A, E, diffE, minimumf, maximumf, Vebitmax, checks, \
             number, numbers, cavlist, factor, cavmaxCSS, cavmaxreal):
    Q = range(1 , Qin + 1, 1)
    for i in Q:
        Vebit = 12*A/i   
# Ist possibility: fixed number, compute Energy
        if checks == [1, 0, 0, 1]:
            compute_energy(number, A, phi,  i, cavlist, Vebit, Vebitmax, cavmaxCSS, factor, betaS)
        elif checks == [1, 0, 1, 0]:
            compute_field(number, A, phi, i, Vebit, Vebitmax, cavmaxreal, factor, betaS, minimumf, maximumf, diffE, E)
        elif checks == [0, 1, 1, 0]:
        # for some reason: after checks no for..
            normann = 3
            for j in numbers:
                compute_field(j, A, phi, i, Vebit, Vebitmax, cavmaxreal, factor, betaS, minimumf, maximumf, diffE, E)  
   	else:
            refresh()

def clickrow(Qcont, A1, nameiso, abu, qdivbya, abu2, information, A, diffqa0, check3, check4, factor, \
             phi, minimumf, maximumf, cavmaxreal, combo):
    class SelectionListener(ITableSelectionChangedListener):
        def selectionChanged(self, selection):
            text=""
            for row in selection:
                i=0
                for s in row:
                    text += s;
                    if i != (len(row)-1):
                            text += " "
                    i+=1
                text1 = text.split()
                
                Qchosen = float(text1[0])
                Number = float(text1[2])
                Energy = float(text1[3])

                
                if check4 == 0 and check3 == 1:
                    for Qchosen, Number, Energy, fieldreal in info_for_click
                        do something
	
if __name__ == '__main__': main()
Danke vielmals im Vorraus. Zur Orientierung: info_for_click kommt in der 4. Zeile von unten vor und ausserdem bei return in compute_fields und auch schon davor in compute_fields

Re: Parameter an Funktionen uebergeben

Verfasst: Montag 19. August 2013, 22:18
von peter99
aja und info_for_click erzeugt dann einen Global Error, das es nicht definiert ist.
NameError: global name 'info_for_click' is not defined

Re: Parameter an Funktionen uebergeben

Verfasst: Montag 19. August 2013, 22:26
von Sirius3
Hallo peter99,
kannst Du für jede Funktion beschreiben, was sie tut; vor allem, was für Inputs und Outputs sie hat.

Re: Parameter an Funktionen uebergeben

Verfasst: Dienstag 20. August 2013, 02:13
von peter99
Die beiden ersten Funktionen: readcontaminationfile und readcavmaxfile lesen Informationen aus tex.-Dateien ein, die eine enthält ein Periodensystem, die andere Kalibrierungsfaktoren. getInputs holt sich die inputs aus den Textfeldern, etc. Aus dem GUI. Anschließend gibt alarm einen Alarm aus, falls der User z.B. zu hohe Beschleunigungsfelder anliegen hat.
Compute_Energy berechnet die Energie bei gegebenen Feld, compute_field berechnet Feld bei gegebener Energie. Decision berechnet je nachdem, was für Entscheidungen der User getroffen hat, Feld oder Energie und gibt eine gepaarte Ergebnisse: Energie, charge state, Nummer an Beschleunigungstationen an eine Tabelle auf. Click row zeigt dann die Verschmutzung eines Charge states an mithilfe des Periodensystems an und gibt das in einer zweiten Tabelle aus. Zudem zeigt es wenn man die Entscheidung getroffen hat die Energie festzulegen die Felder an. Ich will nun aber in der clickrow Funktion nicht nochmals die Felder berechnen, damit sie angezeigt werden – weil das Rechenleistung kostet und unschön ist. Ich hoffe, das macht alles etwas besser. Aja und refresh soll z.B. Ergebnisse zurücksetzen, wenn das Programm mehrmals hintereinander durchlaufen wird

Re: Parameter an Funktionen uebergeben

Verfasst: Dienstag 20. August 2013, 02:16
von peter99
compute_field sollte mir demnach die Felder zurückgeben, gekoppelt mit der Information charge state etc. ...
deswegen zippe ich die sachen immer, da ich nicht so gut mir Klassen bin..
ich hoffe, dass das die Information war, die du wolltest

Re: Parameter an Funktionen uebergeben

Verfasst: Dienstag 20. August 2013, 03:23
von peter99

Code: Alles auswählen

def compute_field(s, A, phi,  k, Vebit0, Vebitmax, cavmaxreal, factor, betaS, minimumf, maximumf, diffE, E):
    E_average = (600 + E)/2
    v_averge = sqrt(2*E_average*1.602177*10**(-16)/1.6726*10**27)
    beta_average = v_averge/c0
    tmp = pi * geff / (beta_average * Lambda)
    T_average = sin(tmp)/tmp*sin(pi*betaS/(2*beta_average))
    fieldreal = diffE*A/(27.98*k*float(s)*T_average*cos(phi))
    listfields = [fieldreal]* int(s)
    # cannot be defined earlier because otherwise listfields not already defined
    condition_field = (
    all(fieldreal > minimumf and fieldreal < maximumf and t < u for t, u in zip(listfields, cavmaxreal)) and Vebit0 < Vebitmax
    )
    if condition_field:
        Qout.append(k)
        fieldout.append(fieldreal)
        numberout.append(s)
        Energyout.append(E)
        set_cells(table, len(Qout) - 1, k, Vebit0, s, E)
    # no provide information for click
  #  info_for_click = zip(Qout, fieldout, numberout, Energyout)
   # else:
      #  refresh()
    #return info_for_click

def decision(phi, Qin, A, E, diffE, minimumf, maximumf, Vebitmax, checks, \
             number, numbers, cavlist, factor, cavmaxCSS, cavmaxreal):
    Q = range(1 , Qin + 1, 1)
    for i in Q:
        Vebit = 12*A/i   
# Ist possibility: fixed number, compute Energy
        if checks == [1, 0, 0, 1]:
            compute_energy(number, A, phi,  i, cavlist, Vebit, Vebitmax, cavmaxCSS, factor, betaS)
            # does not provide any information - not needed
        elif checks == [1, 0, 1, 0]:
            compute_field(number, A, phi, i, Vebit, Vebitmax, cavmaxreal, factor, betaS, minimumf, maximumf, diffE, E)
            info_for_click = zip(Qout, fieldout, numberout, Energyout)
        elif checks == [0, 1, 1, 0]:
        # for some reason: after checks no for..
            normann = 3
            for j in numbers:
                compute_field(j, A, phi, i, Vebit, Vebitmax, cavmaxreal, factor, betaS, minimumf, maximumf, diffE, E)
                info_for_click = zip(Qout, fieldout, numberout, Energyout)
   	else:
            refresh()
    return info_for_click



def clickrow(info_for_click, Qcont, A1, nameiso, abu, qdivbya, abu2, information, A, diffqa0, check3, check4, factor, \
             phi, minimumf, maximumf, cavmaxreal, combo):
    class SelectionListener(ITableSelectionChangedListener):
        def selectionChanged(self, selection):
            text=""
            for row in selection:
                i=0
                for s in row:
                    text += s;
                    if i != (len(row)-1):
                            text += " "
                    i+=1
                text1 = text.split()
                
                Qchosen = float(text1[0])
                Number = float(text1[2])
                Energy = float(text1[3])

                
                if check4 == 0 and check3 == 1:
                    for Qchosen, fieldreal, Number, Energy in info_for_click:
                        listfields = int(Number)*[fieldreal]
                        for i in range(1, int(Number) + 1,1):
                            #if fieldreal > minimumf and fieldreal < maximumf and all(t < u for t, u in zip(listfields, cavmaxreal)):
                            display.getWidget("cav" + str(i)).setPropertyValue("visible",True)
                            display.getWidget("cav" + str(i) + "real").setPropertyValue("visible",True)
                            display.getWidget("cav" + str(i)+ "real").setValue(fieldreal)
                        for m in range(int(Number) + 1, 7, 1):
                            display.getWidget("cav" + str(m)).setPropertyValue("visible",False)
                            display.getWidget("cav" + str(m) + "real").setPropertyValue("visible",False)
                        for h in range(1, int(Number) + 1, 1):
                            x = listfields[h-1]*factor[h-1]
                            display.getWidget("cav" + str(h)).setValue(x)
                        
                beamqdivbya = Qchosen/float(A)
#Here either prints out all contamination or only stable contamination
                TESTS = {
                    "all": lambda a,b,c,d,e: True,
                    "stable": lambda a,b,c,d,e: float(e)>0
                }
                
                test = TESTS[combo]
                
                result = []
                for a,b,c,d,e in zip(qdivbya,Qcont,nameiso, A1,abu2):
                    if test(a,b,c,d,e):
                        diffqa = abs(beamqdivbya - a )
                        if diffqa < diffqa0:
                            diffqaoverqa = float(diffqa)/float(Qchosen)* A
                            result.append(a)
                            set_cells(table1, len(result)-1, c, b, d, a, diffqaoverqa, e)

    table.addSelectionChangedListener(SelectionListener())
	
if __name__ == '__main__': main()
das funktioniert, ist aber wiederum sehr unschön-.-

Re: Parameter an Funktionen uebergeben

Verfasst: Dienstag 20. August 2013, 03:23
von peter99

Code: Alles auswählen

def compute_field(s, A, phi,  k, Vebit0, Vebitmax, cavmaxreal, factor, betaS, minimumf, maximumf, diffE, E):
    E_average = (600 + E)/2
    v_averge = sqrt(2*E_average*1.602177*10**(-16)/1.6726*10**27)
    beta_average = v_averge/c0
    tmp = pi * geff / (beta_average * Lambda)
    T_average = sin(tmp)/tmp*sin(pi*betaS/(2*beta_average))
    fieldreal = diffE*A/(27.98*k*float(s)*T_average*cos(phi))
    listfields = [fieldreal]* int(s)
    # cannot be defined earlier because otherwise listfields not already defined
    condition_field = (
    all(fieldreal > minimumf and fieldreal < maximumf and t < u for t, u in zip(listfields, cavmaxreal)) and Vebit0 < Vebitmax
    )
    if condition_field:
        Qout.append(k)
        fieldout.append(fieldreal)
        numberout.append(s)
        Energyout.append(E)
        set_cells(table, len(Qout) - 1, k, Vebit0, s, E)
    # no provide information for click
  #  info_for_click = zip(Qout, fieldout, numberout, Energyout)
   # else:
      #  refresh()
    #return info_for_click

def decision(phi, Qin, A, E, diffE, minimumf, maximumf, Vebitmax, checks, \
             number, numbers, cavlist, factor, cavmaxCSS, cavmaxreal):
    Q = range(1 , Qin + 1, 1)
    for i in Q:
        Vebit = 12*A/i   
# Ist possibility: fixed number, compute Energy
        if checks == [1, 0, 0, 1]:
            compute_energy(number, A, phi,  i, cavlist, Vebit, Vebitmax, cavmaxCSS, factor, betaS)
            # does not provide any information - not needed
        elif checks == [1, 0, 1, 0]:
            compute_field(number, A, phi, i, Vebit, Vebitmax, cavmaxreal, factor, betaS, minimumf, maximumf, diffE, E)
            info_for_click = zip(Qout, fieldout, numberout, Energyout)
        elif checks == [0, 1, 1, 0]:
        # for some reason: after checks no for..
            normann = 3
            for j in numbers:
                compute_field(j, A, phi, i, Vebit, Vebitmax, cavmaxreal, factor, betaS, minimumf, maximumf, diffE, E)
                info_for_click = zip(Qout, fieldout, numberout, Energyout)
   	else:
            refresh()
    return info_for_click



def clickrow(info_for_click, Qcont, A1, nameiso, abu, qdivbya, abu2, information, A, diffqa0, check3, check4, factor, \
             phi, minimumf, maximumf, cavmaxreal, combo):
    class SelectionListener(ITableSelectionChangedListener):
        def selectionChanged(self, selection):
            text=""
            for row in selection:
                i=0
                for s in row:
                    text += s;
                    if i != (len(row)-1):
                            text += " "
                    i+=1
                text1 = text.split()
                
                Qchosen = float(text1[0])
                Number = float(text1[2])
                Energy = float(text1[3])

                
                if check4 == 0 and check3 == 1:
                    for Qchosen, fieldreal, Number, Energy in info_for_click:
                        listfields = int(Number)*[fieldreal]
                        for i in range(1, int(Number) + 1,1):
                            #if fieldreal > minimumf and fieldreal < maximumf and all(t < u for t, u in zip(listfields, cavmaxreal)):
                            display.getWidget("cav" + str(i)).setPropertyValue("visible",True)
                            display.getWidget("cav" + str(i) + "real").setPropertyValue("visible",True)
                            display.getWidget("cav" + str(i)+ "real").setValue(fieldreal)
                        for m in range(int(Number) + 1, 7, 1):
                            display.getWidget("cav" + str(m)).setPropertyValue("visible",False)
                            display.getWidget("cav" + str(m) + "real").setPropertyValue("visible",False)
                        for h in range(1, int(Number) + 1, 1):
                            x = listfields[h-1]*factor[h-1]
                            display.getWidget("cav" + str(h)).setValue(x)
                        
                beamqdivbya = Qchosen/float(A)
#Here either prints out all contamination or only stable contamination
                TESTS = {
                    "all": lambda a,b,c,d,e: True,
                    "stable": lambda a,b,c,d,e: float(e)>0
                }
                
                test = TESTS[combo]
                
                result = []
                for a,b,c,d,e in zip(qdivbya,Qcont,nameiso, A1,abu2):
                    if test(a,b,c,d,e):
                        diffqa = abs(beamqdivbya - a )
                        if diffqa < diffqa0:
                            diffqaoverqa = float(diffqa)/float(Qchosen)* A
                            result.append(a)
                            set_cells(table1, len(result)-1, c, b, d, a, diffqaoverqa, e)

    table.addSelectionChangedListener(SelectionListener())
	
if __name__ == '__main__': main()
das funktioniert, ist aber wiederum sehr unschön-.-

Re: Parameter an Funktionen uebergeben

Verfasst: Dienstag 20. August 2013, 08:25
von snafu
Ein Verbesserungsvorschlag zu `compute_fields()`. Du defnierst darin ja folgendes:

Code: Alles auswählen

fieldreal = diffE*A/(27.98*k*float(s)*T_average*cos(phi))
listfields = [fieldreal]* int(s)
`listfields` enthält also eine Liste der Größe `s`, in der einfach immer nur der Wert `fieldreal` vorkommt.

Dann machst du folgendes:

Code: Alles auswählen

condition_field = (
all(fieldreal > minimumf and fieldreal < maximumf and t < u for t, u in zip(listfields, cavmaxreal)) and Vebit0 < Vebitmax
)
Zunächst einmal lässt sich der Teil `fieldreal > minimumf and fieldreal < maximumf` auch etwas lesbarer als `minimumf < fieldreal < maximumf` ausdrücken. Und dann verstehe ich nicht, wieso du das überhaupt ständig an der Stelle testest. Denn dein Minimum und Maximum sind Argumente der Funktion, die nirgendwo überschrieben werden und `fieldreal` ist - wie oben zu sehen - ebenfalls konstant. Den Kram kannst du also vor Betreten der Schleife einmalig überprüfen und dann ggf andere Dinge zur Erfüllungen deiner `condition` durchführen. Auch das Zippen finde ich unnötig, da `listfields` ja ausschließlich gleiche Werte enthält.

Letztlich sollte also folgender Code äquivalent sein:

Code: Alles auswählen

precondition = minimumf < fieldreal < maximumf and Vebit0 < Vebitmax
if precondition and all(cavmax > fieldreal for cavmax in cavmaxreal):
    Qout.append(k)
    # u.s.w
Achja, und du weißt schon, dass du deine Funktion als "compute_field*s*" definiert hast, in `decision()` aber "compute_field" (ohne das "s" am Ende) aufrufen willst...?