Seite 1 von 2

Anfänger Hilfe zu Sequenzen, Dict...

Verfasst: Montag 14. Mai 2007, 09:15
von ete
Hallo!

Ich brauch mal wieder eure Hilfe...

Ich bin dabei mein erstes (nützliches) Programm zu Programmieren und habe folgendes Problem:

Es sei eine Sequenz gegeben z.B. attggccaa

Je zwei bestimmten Buchstaben soll ein gewisser Wert zugeordnet werden z.B. at=9,8 ; tt=11,1 ; tg=5,1 ;gg=4,5 usw.

Jetzt hab ich dies in eine Library gepackt und es haben sich folgende Probleme ergeben:

1) Wenn doppelte Paare auftreten, werden diese nicht mit angezeigt (z.B. 2 mal tt soll auch 2 mal 11,1 angeben, wird aber nur als eines ausgeben)

2) Ich möchte die Werte später für eine Formel weiter verwenden und weiss nicht wie ich das anstellen soll (bis jetzt hab ich nur eine print Ausgabe).

Nun meine Frage:

Ist es sinnvoll für die Fragestellung eine Library zu erstellen oder gibt es einen einfacheren Weg? Wenn ja, wie kann ich stäter mit den Werten weiter arbeiten?

Ein Schalgwort oder Link ist auch hilfreich, denn ich weiss nicht unter welchem Topic ich nachschauen soll...

Danke schonmal :D und nicht Lachen-bin blutige Anfängerin...

ete

Verfasst: Montag 14. Mai 2007, 10:38
von BlackJack
Zu wenig Informationen. Was heisst "in eine Library" gepackt? Und hat es vorher so funktioniert wie Du wolltest? Wies sieht Dein Code aus?

Mir ist auch nicht ganz klar was Du als Rückgabe der Funktion(?) haben möchtest. Eine Liste mit Werten? Eine Summe? Sollen auch überlappende Buchstabenkombinationen in das Ergebnis eingehen? Also ist 'attg' als einmal 'at' und einmal 'tg' zu sehen oder als 'at', 'tt' und 'tg'? Gibt es zu allem möglichen Zwei-Buchstaben-Kombinationen von 'atgc' einen Wert, oder gibt es auch Ausnahmen?

Verfasst: Montag 14. Mai 2007, 11:19
von Zizibee
BlackJack hat geschrieben:Also ist 'attg' als einmal 'at' und einmal 'tg' zu sehen oder als 'at', 'tt' und 'tg'?
Laut ihrem Beispiel müsste 'attg' in 'at', 'tt' und 'tg' aufgesplittet werden, glaub ich zumindest...

Was heißt denn dieser Teil?
ete hat geschrieben:1) Wenn doppelte Paare auftreten, werden diese nicht mit angezeigt (z.B. 2 mal tt soll auch 2 mal 11,1 angeben, wird aber nur als eines ausgeben)
2 mal 'tt' wäre ja eigentlich 'tttt', wenn ich das Beispiel hier
ete hat geschrieben:Es sei eine Sequenz gegeben z.B. attggccaa
Je zwei bestimmten Buchstaben soll ein gewisser Wert zugeordnet werden z.B. at=9,8 ; tt=11,1 ; tg=5,1 ;gg=4,5 usw.
richtig verstanden habe, dann müsste doch schon bei 'ttt' das zwei mal ausgegeben werden, oder?

Verfasst: Montag 14. Mai 2007, 11:54
von BlackJack
Ups, ich hatte die Wertezuordnung nicht im Zusammenhang mit der Beispielzeichenkette gesehen. :oops:

Verfasst: Montag 14. Mai 2007, 14:00
von Rebecca
Vielleicht meint sie mit "Libraries" Dictionairies?

Verfasst: Montag 14. Mai 2007, 16:11
von ete
Sorry für die schlechte Erläuterung :roll:

Also noch mal von vorne:

Ich habe eine Sequenz z.B.

attagctt

2 Buchstaben müssen einen bestimmten Wert bekommen.Jeweils der 1. mit dem 2. , dann der 2. mit dem 3. , der 3. mit dem 4. usw...Also at; ag;ac;aa usw. Wobei der Wert für die Paare immer gleich bleibt.

In meinem Beispiel brauche ich die Werte für

at
tt
ta
ag
gc
ct
und tt.

Später möchte ich die Summe aller Werte zusammen rechnen.
Ich hatte nun ein Dictionairý erstellt:
at:11.1 ; tt:5.0 usw.

Wenn ich die einzelnen 2er mit einer print Anweisung aus dem dic abfrage, bekomme ich die richtigen Werte ausgeben. Aber leider nur ein mal tt anstatt von 2 mal tt (wenn man mein Bsp. betrachtet). Und auserdem weiss ich nicht, wie ich mit den Werten später rechnen kann...Vielleicht ist auch der Ansatz mit meinen Dic vollkommen falsch...

War das verständlicher? Code hab ich gerade nicht zur Hand, kann ich morgen posten...

Verfasst: Montag 14. Mai 2007, 16:14
von jens
Du willst uns aber bestimmt nicht eine Aufgabe die du lösen sollst, uns lösen lassen, oder?
Bitte mal das lesen: http://www.python-forum.de/topic-1689.html

Also im Grunde must du die Buchstabenreihe in zweier Gruppen aufteilen. Dann benötigst du noch ein dict mit den Buchstaben<->Werte Verhältnissen und los gehts...

Verfasst: Montag 14. Mai 2007, 16:45
von BlackJack
@ete: Die Idee mit dem Dictionary für die Werte ist schon nicht schlecht. Dann musst Du in einer Schleife über die Zeichenkette gehen. Hier hätten wir mal einen der seltenen Fälle wo der Zugriff über einen Index Sinn macht. In jedem Schritt musst Du zwei Zeichen aus der Zeichenkette per Slice-Notation ausschneiden und im Dictionary den Wert raussuchen. Den dann entweder an eine Liste anfügen oder gleich aufsummieren, je nachdem ob die Einzelwerte benötigt werden oder nicht.

Verfasst: Dienstag 15. Mai 2007, 07:45
von ete
Danke schonmal für die Tips...Und zur Info, ich bin BTA am Pflanzeninstitut und bin dabei mir selber Python mit Büchern anzueignen. Habe weder Abitur, noch bin ich an der Uni...Ich kenne leider niemanden der Python kann...

Ich werd mal weiter probieren.

Um etwas Übung zu bekommen, suche ich mir Programme, die ich selber brauche um dadurch zu lernen...

ciao ete

Verfasst: Freitag 18. Mai 2007, 07:51
von ete
Also ich hab gestern den ganzen Tag probiert und komm nicht weiter :(

Hier mein Problem:

ich weiss nicht wie ich in jedem Schritt der Schleife auf den Index so zugreiffe, das nach jeder Runde die Indexzahlen um eins erhöht werden.

Im 1. Schritt wäre das ja [0:2] , im 2. [1:3] usw. Ich hab alle Referencen durchforstet und nirgends ein ähnliches Bsp. gefunden.

Dann hab ich überlegt das ganze über split() zu machen, komme aber auch nicht weiter...

Danke schonmal :)

Verfasst: Freitag 18. Mai 2007, 08:15
von EyDu

Code: Alles auswählen

for i in xrange(len(text)-2):
    print text[i:i+2]

Verfasst: Freitag 18. Mai 2007, 08:29
von ete
Aha...Jetzt kann ich weiter machen...Vielen Dank!

:wink:

Verfasst: Freitag 18. Mai 2007, 08:45
von Zizibee
Ich hab da auch mal was versucht. Der Vorschlag von EyDu ist zwar eigentlich der Selbe, aber da ich mir jetzt die "Mühe" gemacht habe es zu schreiben, kann ich es ja trotzdem posten ;)

Code: Alles auswählen

string ="attagctt"
wert = 0

for i in range(len(string)-1):
	paar = string[i:i+2]
	
	if paar == 'ag':
		wert += 1.2
	elif paar == 'at':
		wert += 1.5
	elif paar == 'ct':
		wert += 2.3
	elif paar == 'gc':
		wert += 1.8
	elif paar == 'ta':
		wert += 2.4
	elif paar == 'tt':
		wert += 0.2

print 'Summe: ', wert
Das ist bestimmt nicht die sauberste oder beste Lösung, aber besser kann ich es nicht und es funktioniert :)

[EDIT:] Ausgabe ist:
Summe: 9.6

Verfasst: Freitag 18. Mai 2007, 09:57
von keppla
Zizibee hat geschrieben:Das ist bestimmt nicht die sauberste oder beste Lösung, aber besser kann ich es nicht und es funktioniert :)
eine funktionierende Lösung ist einer eleganten, aber nicht funktionierenden Lösung vorzuziehen. Und schlecht ist die Lösung sicher nicht.
Was man eleganter machen könnte, wäre, die paar/werte-beziehungen in ein dictionary packen, da sie eher Daten als Programmlogik sind,
Also Statt deines if-blocks:

Code: Alles auswählen

werte = {
  'ag' : 1.2,
  'at' : 1.5,
 # ...
}
if paar in werte:
  wert += werte[paar]
aber, wie gesagt, dass sind eher Stilfragen

Verfasst: Freitag 18. Mai 2007, 14:22
von ete
Ich hatte es auch über ein Dictonary gemacht, bis ich dann nicht weiter kam...Am Anfang wollte ich es auch über die If Funktion machen, war dann aber zu Faul alle Werte einzugeben (sind zeimlich viele)...

Ist es egal ob man xrange oder range benutzt?

Jetzt kann ich wieder ruhig schlafen :) Danke!


Achja (len(text)-2) muss übrigens -1 sein, da sonst das letzte Paar fehlt...Nur falls das noch jemand benutzen möchte...


ciao ete

Verfasst: Freitag 18. Mai 2007, 14:44
von keppla
Ist es egal ob man xrange oder range benutzt?
im prinzip ja.
range gibt als Antwort eine liste, in der die Werte stehen, xrange einen iterator, der die zahlen on-the-fly erzeugt, womit xrange weniger Speicher benötigt.
Aber praktisch gesehen ist es eigentlich egal, und gerade als Anfänger sollte man die Finger von Optimierung lassen.

Verfasst: Freitag 18. Mai 2007, 17:13
von thelittlebug
bei

Code: Alles auswählen

for x in range(10**7): pass
schnappt sich Python ~150MB Ram, bei 10**8 wären das ja dann ~1,5GB Ram wo xrange eigentlich "keinen merkbaren" Ramverbrauch hat.

Ich hätte eher behauptet das es darauf ankommt, brauche ich die Liste die range zurückliefert dann bleib ich dabei. Gehts darum ne Schleife zu bauen würd ich xrange nehmen.

lgherby

Verfasst: Dienstag 22. Mai 2007, 16:29
von ete
Vielen Dank für die Erklärung!


Ich habs jetzt fertig und es funktioniert...

Mein nächstes Ziel ist dann, das ganze mit Tkinter grafisch zu programmieren...Ich kann ja mein Grundgerüst mal posten :roll:

Code: Alles auswählen

# Tm Berechnung

from math import*


sequenz=raw_input("Please enter your sequenz!")
string=sequenz

t=sequenz.count("t")
a=sequenz.count("a")
g=sequenz.count("g")
c=sequenz.count("c")

# Basis < 13 Nukleotide
# Tm=2°C (A+T) + 4°C (G+C)

def methode01():
    global t,a,g,c
    Tm01=(2*(a+t))+(4*(g+c))
    print Tm01


# Basis > 13 Nukleotide
# Tm=64.9+41*(G+C-16.4)/(A+T+G+C)

def methode02():
    global t,a,g,c
    Tm02=64.9+41*(g+c-16.4)/(a+t+g+c)
    print Tm02


# Salzkonezntration 14-70 N
# Tm=81,5°C + 16,6 * (log[M+]) + 0,41 * (%G+C) -(500/N)

def methode03():
    global t,a,g,c
    M=raw_input("Please enter the salt conc in mol/L without unit!")
    GC=(float(g)+float(c))/(float(t)+float(a)+float(g)+float(c))*100 # auf und abrunden!?
    N=t+a+g+c
    Tm03=81.5+16.6*(log10(float(M)))+0.41*float(GC)-(500.0/float(N))
    print Tm03

# Nearest Neighbour Methode

def methode04():

    global string

    kalium=input("Please enter the M Kalium in mol/L")
    magnesium=input("Please enter the M Magnesium in mol/L")
    enden=input("Wieviel überhängende Enden?")
    primer=input("Please enter your primer concentration in mol/L")

    ### Enthalpie H

    # Wärmemenge, die bei konst Temperatur, Druck und Volumen aufgenommen oder abgeben wird.
    # Berechnet aus Enthalpie der Reaktionsproukte minus der Enthalpie der Reaktanten.
    # Einheit kcal/mol

    werte = {"aa":-9.1 , "ac":-6.5 , "ag":-7.8 , "at":-8.6 ,
            "ca":-5.8 , "cc":-11.0 , "cg":-11.9 , "ct":-7.8 ,
            "ga":-5.6 , "gc":-11.1 , "gg":-11.0 , "gt":-6.5 ,
            "ta":-6.0 , "tc":-5.6 , "tg":-5.8 , "tt":-9.1}
    wertH=0
    
    for i in xrange(len(string)-1):
        paar = string[i:i+2]
        if paar in werte:
                wertH +=werte[paar]

    enthalpie_he = (-5000 * enden) / 1000          # in kcal/mol

    gesamt_enthalpie_h_kcalmol = wertH + (enthalpie_he)  

    enthalpie_h = gesamt_enthalpie_h_kcalmol * 1000     # Ergebnis in cal/mol
   


    ### Freie Energie G
    
    werte = {"aa":-1.55 , "ac":-1.40 , "ag":-1.45 , "at":-1.25 ,
            "ca":-1.15 , "cc":-2.30 , "cg":-3.05 , "ct":-1.45 ,
            "ga":-1.15 , "gc":-2.70 , "gg":-2.30 , "gt":-1.40 ,
            "ta":-0.85 , "tc":-1.15 , "tg":-1.15 , "tt":-1.55}
            
    wertG=0
            
    for i in xrange(len(string)-1):
        paar = string[i:i+2]
        if paar in werte:
                wertG +=werte[paar]

    freie_energie_ge = enden * -1000 / 1000          # in kcal/mol

    gesamt_freie_energie_g_kcalmol = wertG + (freie_energie_ge) + 2.2   

    g = gesamt_freie_energie_g_kcalmol * 1000      # Ergebnis in cal/mol

    ### Salzkonzentration

    s =(kalium)+4*(magnesium)**0.5         # Ergebnis

    ### Tm Formel

    upper = 298.2 * (enthalpie_h)
    lower = enthalpie_h - (g) + 1.99 * (298.2)* log(4*10**-7)
    l = 1.0 + 0.7 * (s)
    salz = s / l
    ls =log10(salz)

    tm = (upper/lower) + 16.6 * ls - 269.3

    return tm
Jetzt hab ich 2 Fragen

1) Kann ich es so programmieren, das mehrere Sequenzen sich berechnen lassen z.B. aus einer Text Datei raus? Ich habe ca. 500 Sequenzen.

2) Kann ich die Ausgabe von 1 in ein Excel file mit diesem Code http://www.python-forum.de/topic-10136. ... ight=excel exportieren?

Danke schonmal :)

ete

Verfasst: Dienstag 22. Mai 2007, 18:21
von BlackJack
Du solltest am besten erst einmal die ``global``-Anweisungen aus dem Programm entfernen und dann vergessen, dass es diese Anweisung gibt. So auf den ersten Blick wird auch gar keine von den Anweisungen in dem Pogramm benötigt.

Werte sollten Funktionen in der Regel als Argumente betreten und als Rückgabewerte verlassen. Damit bleibt das Programm übersichtlicher und durchschaubarer und die Funktionen sind auch entkoppelter und lassen sich leichter einzeln testen und verwenden.

Auf Modulebene sollte so wenig wie möglich ausführbarer Code stehen. Der wird nur beim importieren ausgeführt, lässt sich also nicht wiederverwenden oder innerhalb eines Programmes noch einmal ausführen.

Zeilen sollten 80 Zeichen nicht überschreiten, damit der Text lesbar bleibt, unter anderem auch in Medien wie E-Mail oder `diff`\s. Vor und nach Operatoren wie zum Beispiel der Zuweisung ausserhalb von Argumentlisten für Funktionsdefinitionen und -aufrufe, und nach Kommata und Doppelpunkten, sollte ein Leerzeichen stehen.

Zuviele Namen in einer Funktion machen das ganze ein wenig unübersichtlich. `methode04()` ist ein wenig zu Umfangreich. Zum Beispiel wird `g` von der Modulebene verwendet, dann aber innerhalb der Funktion an einen anderen Wert gebunden. So etwas kann schnell zu Verwirrungen und eventuell Fehlern führen. `primer` wird anscheinend gar nicht verwendet.

Die `input()`-Funktion sollte man nach Möglichkeit nicht verwenden. Dort kann der Benutzer beliebigen Python-Code angeben, der ausgeführt wird! Sicherer ist `raw_input()` zu verwenden und den Rückgabewert entsprechend umzuwandeln. `float()` wird an einigen Stellen unnötig oft verwendet. Problematisch ist eigentlich nur die Division, weil die im Normalfall nur eine Fliesskommazahl als Ergebnis liefert, wenn mindestens einer der Operanden eine Fliesskommazahl ist. Das kann man aber mit einem ``from __future__ import division`` als ersten Import ändern. Dann sind alle Divisionen mit ``/`` Fliesskommadivisionen. Wenn man eine Ganzzahldivision haben möchte nimmt man den ``//``-Operator.

Natürlich kann man auch Werte für Sequenzen aus einer Datei berechnen. Dazu schreibt man am besten eine Funktion die alle nötigen Werte zur Berechnung und die Sequenz als Argument entgegennimmt. Die ruft man dann nacheinander mit allen Sequenzen aus der Datei auf.

In der `methode04()` gibt es sich wiederholenden Quelltext, den man in eine Funktion auslagern kann. Zum Beispiel auf der Sequenz anhand eines Dictionaries eine Summe für die Paare zu berechnen.

Mit OOP kann man auch einiges besser Strukturieren. Zum Beispiel ein `Sequence`-Objekt, dass weiss wieviele 'a', 't', 'g' und 'c' es enthält und für diese "Paarsummen" eine Methode bereithält.

Beispiel:

Code: Alles auswählen

class Sequence(object):
    def __init__(self, data):
        self.data = data
        self.a = data.count('a')
        self.c = data.count('c')
        self.g = data.count('g')
        self.t = data.count('t')
    
    def __len__(self):
        return len(self.data)
    
    def __getitem__(self, key):
        return self.data[key]
    
    def pair_sum(self, weights):
        return sum(weights.get(self[i:i+2], 0) for i in xrange(len(self)))


def test():
    sequence = Sequence('gattaca')
    print len(sequence)     # -> 7
    print sequence.a, sequence.c, sequence.g, sequence.t    # -> 3 1 1 2
    
    weights = {"aa": -9.1, "ac": -6.5, "ag": -7.8, "at": -8.6,
               "ca": -5.8, "cc": -11.0, "cg": -11.9, "ct": -7.8,
               "ga": -5.6, "gc": -11.1, "gg": -11.0, "gt": -6.5,
               "ta": -6.0, "tc": -5.6, "tg": -5.8, "tt": -9.1}
    print sequence.pair_sum(weights)    # -> -41.6

Verfasst: Mittwoch 23. Mai 2007, 15:28
von ete
Danke für die Tips, ich werds sie gleich mal umsetzen :o