listdir- aus 2 gleichen files- daten lesen+suchen

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.
martina
User
Beiträge: 29
Registriert: Montag 19. Januar 2009, 17:45

Halllo,
ich bin noch Pythonanfänger und habe ein Problem.
ich möchte ein kleines Skript was mittels sys.argv schon funktioniert, so automatisieren das es mir dateien eines bestimmten Formates eines gesamten Ordners abarbeitet.

Das zu lesende File(xdom) hat folgendes Format :
>ID
start end name zahl

würde dann zb so aussehen

>gi|76577793|gb|ABA54179.1| 210
48 64 PF00036 6.5
71 99 PF00036 0.00038
108 136 PF00036 0.00015
152 180 PF00036 5.3e-06

aus einem zweiten File, gleichen namen wie xdom (nur .fasta)sollen die zugehörigen Daten gesucht werden, sieht wie folgt aus
>Ara.784
HNBGTTGGJKKMN

und alles in ein neues file geschrieben werden.

Habe das Skript auch schon versucht umzustellen, was mich soweit gebracht hat das ich gleichbenannte Files finde und lese. Jedoch bekomme ich als Ausgabe im neuen File nur einmal den namen aus dem xdom, jedoch nicht die zugehörige sequenz.
Um zu sehen was alles gelesen wird, habe ich ein

Code: Alles auswählen

 print start, end, name

vom xdom genutzt, welches mir auch alle im xdom enthaltenen zeilen angibt.

Ich habe schon dies und das versucht , jedoch habe ich bis nun keine lösung gefunden bzw meinen Fehler gefunden.
:oops:

Besonders verwirrend find ich, dass das Skript mit Argumenteingabe einwandfrei gelaufen ist.

Wäre echt super wenn mir jemand weiterhelfen könnte bzw einen wink mit dem Zaunpfahl gibt, wo mein Fehler ist.


:oops:

hier noch mein Code, hab auch versucht viel zu dokumentieren:

Code: Alles auswählen

import os,sys
x=os.listdir('.')

for file in x:                              # alle files im Ordner
    if "fasta" in file:                    #nur files mit fasta endung
        seq = ""
        for line in file:                   #jede Zeile in fasta
            if ">" in line:                 #wenn > in Zeile überspring  
                continue
            seq += line.replace("\n","")
            fasta=file.split('.')[0]          #split name
        for line in open(fasta+"._0.1.pfam.10.xdom"):      #zeile im xdom mit gleichem anfangs-namen                              
            if ">" in line:
               continue
            start, end ,name= line.split("\t")[0:3]               #merke start, end, name
            print start, end,name                                      #schreibe start, end name
            output=open(fasta+"._0.1.pfam.10.fasta",'w').write(">"+ name + \n"+seq[int(start)-1:int(end)]+"\n")  #schreibe start, ende name in neues file mit gleichem namen nur neuer endung
Vielen lieben Dank schonmal an alle fleißigen Helfer

LG Martina :)
BlackJack

@martina: `os.listdir()` gibt keine Dateien zurück, sondern eine Liste von Datei*namen*, also Zeichenketten. `file` ist also an einen Dateinamen gebunden und ``for line in file`` macht da keinen Sinn.

``print`` wäre auch da Dein Freund zur Fehlersuche gewesen.

Insgesamt ist es ein wenig unsauber Dateien nicht explizit zu schliessen. Du solltest da ein wenig schreibfreudiger sein und ordentliche Namen für die Dateiobjekte springen lassen. :-)

Wenn Du auf die Endung prüfen willst ist ``in`` unsicher weil das auch wahr ist, wenn 'fasta' irgend wo im Dateinamen vorkommt. Besser ist ``filename.endswith('.fasta')``.

In der letzten Zeile sollte Dir das Syntaxhighlighting verraten, dass da etwas nicht stimmt.

Und `output` würde hier immer an `None` gebunden, weil das der Rückgabewert der `write()`-Methode ist.

Insgesamt hilft es vielleicht ein wenig strukturierter vorzugehen und das ganze in Teilaufgaben zu zerlegen, die von Funktionen gelöst werden.
martina
User
Beiträge: 29
Registriert: Montag 19. Januar 2009, 17:45

Hi BlackJack,

zuerst einmal,vielen Dank für die schnelle Antwort.

ICh bin auch noch Pythonanfänger,deswegen sieht dieser Code, wie Du meintest etwas wirr aus...ich gebe mir Mühe es zu lernen und zu verbessern, deshalb bin ich sehr froh über Deine Anmerkungen.

Zwecks der Funktionen muß ich erst noch einmal nachlesen, wie ich das schreiben muß.

Leider habe ich den Fehler in der letzten Zeile noch nicht gefunden, werde aber nicht aufgeben udn weiter suchen.

Aber wieso hat write in der letzten Zeile None? Gibt es eine andere Möglichkeit, um die Ergebnisse in ein neues File zu schreiben, außer diese Funktion?...

Grüße,Martina
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

martina hat geschrieben: Aber wieso hat write in der letzten Zeile None? Gibt es eine andere Möglichkeit, um die Ergebnisse in ein neues File zu schreiben, außer diese Funktion?...
Der Rückgabewert von write ist einfach None. Daher macht es wenig Sinn, sich diesen "in einer Variable zu merken". (Bei Dir output).

Man nennt diesen Vorgang auch "binden" ;-)

Also genau: Du öffnest eine Datei und schreibst mit write() etwas hinein. write gibt den Wert "None" zurück. Dieser wird bei Dir an die Variable output gebunden. Dieser letzte Schritt ist sinnlos:

1.) Wird immer ein None zurückgegeben
2.) Du fängst damit nichts an -> wozu sich Dinge merken, die man später nicht mehr "anfasst"?
martina
User
Beiträge: 29
Registriert: Montag 19. Januar 2009, 17:45

Hi Hyperion,

vielen Dank für die Erklärung :idea: ...
also kann ich das write einfach weglassen.
Hab ich mir wohl was falsches 'angewöhnt'.

:lol:

Kann mir vllt noch jemand eine kleine Hilfestellung geben zwecks der Umstellung des Skriptes mit Funktionen und hat vllt noch jemand eine Idee wegen der letzetn Zeile bzw einen Hinweis auf den Fehler?

Wäre echt super, tue mich noch etwas schwer mit Funktionen und allem drum und dran. :oops:

Danke schonmal an Alle
Grüße
Martina
TiKaey
User
Beiträge: 84
Registriert: Montag 24. November 2008, 20:48

Hi,

in der letzten Zeile fehlt ein " vor dem ersten \n.

Ich denke mal, das war gemeint. :o)
martina
User
Beiträge: 29
Registriert: Montag 19. Januar 2009, 17:45

Joa,
:x

stimmt, immer schlimm wenn man davor sitzt und die einfachsten Fehler nicht sieht :oops:

Danke :D
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

martina hat geschrieben: also kann ich das write einfach weglassen.
Nein! Du hast es noch nicht verstanden. Das write brauchst Du - das ist ja gerade die Funktion zum Schreiben einer Datei!

Du brauchst Den Rückgabewert der Funktion write nicht!

Du solltest Dich dringend mit Funktionen auseinandersetzen, ich denke dann wird es Dir klar.

Code: Alles auswählen

# hier variiert der Rückgabewert (abhängig vom Parameter)
def square(value):
    return value*value

# hier ist der Rückgabewert None
# ist immer der Fall, wenn kein explizites return aufgerufen wird
def foo():
    print "Dies Funktion berechnet nichts und hat nichts sinnvolles zurückzugeben!"
    # hier könnte nun ein return stehen, wenn man etwas sinnvolles zurückgeben wollen würde

# wir ruefen square auf und binden es an s
s = square(5)
# nun können wir mit s toll weiter rechnen ...
print s+2

useless = foo()
# useless is useless ;-) wir brauchen den Rückgabewert nicht!
print useless
# same effect:
foo()
Das write() bei Dir verhält ähnlich sich wie foo().
martina
User
Beiträge: 29
Registriert: Montag 19. Januar 2009, 17:45

ok,mein Fehler danke Hyperion.
Hab mich ein wenig mit Funktionen auseinander gesetzt, jedoch weiß ich nicht ganz genau welche Befehle in die Funkionen müssen und welche ich abschließend abarbeite.
Wahrscheinlich ist mein Beispiel auch nicht das Beste für den Einstieg.
Aber vielleicht kann mir jeamdn helfen bzw Tip geben welche Sachen ich ändrn muß.

Wenn ich es laufen lasse sehe ih das die Funktion sequence durchlaufen wird(print).
Er kennt die Variablen name,start und end nicht. Irgendwie komme ich mit dem aufrufen der Funktionen nicht zurecht. :(

Danke imVoraus

Code: Alles auswählen

  
  3 def sequence():
  4     seq=""
  5     for line in file:
  6         if ">" in file:
  7             continue
  8         print 'in sequence'
  9         seq+=line.replace("\n","")
 10 
 11 def domains(start,end,name):
 12     for line in file:
 13         if ">" in line:
 14             continue
 15         print 'in domains'
 16         start,end,name=line.split("\t")[0:3]
 17 
 18 #main
 19 
 20 x=os.listdir('.')
 21 
 22 for file in x:
 23     if file.endswith("fasta"):
 24         sequence()
 25         fname=file.split('.')[0]
 26         fname=open(file+".fasta","w")
 27         for file in x:
 28             if file.endswith(".xdom"):
 29                 domains(start,end,name)
 30                 print 'blub'
 31 print 'out'
 32 output=open(fname+"._0.1.pfam.10.fast",'w')
 33 print output
 34 output=write(">"+name+"\n"+ seq[int(start):int(end)] +"\n")
 35
 36 output.close()
BlackJack

In Zeile 29 wird `domains()` mit den Argumenten `start`, `end`, und `name` aufgerufen. Das geht nicht weil die vorher nie definiert wurden. Welche Werte sollen die an der Stelle denn haben, und warum? So auf den ersten Blick denke ich eher, dass das die Rückgabewerte der Funktion sein sollten und keine Argumente.

Du solltest nicht versuchen komplette Programme zu schreiben und dann testen ob die laufen, sondern das ganze Schritt für Schritt zu entwickeln und immer prüfen ob das Teilprogramm die bisherigen Teilprobleme löst und erst weiter machen, wenn das soweit funktioniert.
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Außerdem muss das "=" in Zeile 34 mit einem Punkt ersetzt werden.
martina
User
Beiträge: 29
Registriert: Montag 19. Januar 2009, 17:45

Hi @ all

danke erstmal für die Hilfe.

Habe nochmal einge Veränderungen/Verbesserungen am Code versucht, jedoch bekomme ich die line.split methode nicht zum laufen. es wird mir immer ein Fehler ausgegeben:

line17
start, end, name=line.split('\t')[0:3]
ValueError: need more than 1 value to unpack
jedoch habe ich bis jetzt keine Lösung dafür gefunden. Besonders da es vorher so funktioniert hat,als ich das Ganze noch nicht mit Funktionen gearbeitet habe.

Zumindest habe ich das Ganze soweit zum LAufen, dass die erste und anschließend die gewünschte zweie Funktion mit der gleichen Datei aufgerufen/abgearbeitet.

Wäre echt dankbar für weitere Hilfe

hier nochmal mein Code:

Code: Alles auswählen

def sequence():
  4     seq=""
  5     for line in file:
  6         if ">" in file:
  7             continue
  8         print 'in sequence'
  9         seq+=line.replace("\n","")
 10         return seq
 11 
 12 def domains():
 13     for line in file:
 14         if ">" in line:
 15             continue
 16         print 'in domains'
 17         start, end, name=line.split('\t')[0:3]
 18         print start,end,name
 19         return start,end,name
 20 
 21 #main
 22 
 23 x=os.listdir('.')
 24 
 25 for file in x:
 26     if file.endswith("fasta"):
 27         sequence()
 28         fname=file.split('.')[0]
 30         print 'test'
 31         for file in x:
 32             if file.endswith(".xdom"):
 33                 domains()
 34                 print 'blub'
 35 print 'out'
 36 output=open(fname+"._0.1.pfam.10.fast",'w')
 37 print output
 38 output.write(">"+name+"\n"+ seq[int(start):int(end)] +"\n")
 39 
 40 output.close()
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wieso prüfst Du denn nicht einmal nach, woran das liegt? Der Fehler ist doch eindeutig:

Code: Alles auswählen

start, end, name=line.split('\t')[0:3]
Du willst durch Dein split drei Stücke an Variablen binden. Du erhältst aber nur eines! Wieso auch immer. Teste doch mal, was line.split() an der Steller ausgibt. Danach guckst Du, was übrig bleibt, wenn Du das Slicing dran hängst. Dann wirst Du dort irgend wo einen Fehler finden, dass nämlich nur ein Teil entsteht.

Ich frage mich vor allem, ob das die richtige Methode ist, was Du da versuchst. Ich meine Du siehst ja jetzt schon, dass Dein Code extrem anfällig für korrekte Formatierung der Input-Daten ist! Im laufenden Betrieb kostet so etwas doch dann nur Nerven.

Vielleicht beschreibst Du noch einmal genau, was Du überhaupt erreichen willst!
martina
User
Beiträge: 29
Registriert: Montag 19. Januar 2009, 17:45

Hi,

also habe noch weiter versucht den Fehler bzw die Fehler zu finden und dabei festgestellt dass ein Fehler im Skript war(wahrscheinlich nicht der einzigste) . :?

Noch einmal zu meinem Problem:

Ich habe mehrere Dateien mit der Endung fasta im Ordner sowie mehrere dazu passende Dateien mit der Endung xdom.
Beide Dateien haben gemeinsame Namensanfänge zb Hubert.fasta und Hubert.xdom, Elli.fasta Elli.xdom.
Nun soll der gesamte Ordner bearbeitet werden, dh Hubert.fasta wird geöffnet und der Inhalt, nach line mit'>' in 'seq' gespeichert.
Anschließend sollen in dem gleichnamigen file Hubert.xdom die start,end und name werte benutzt werden, um in der 'seq' jeweils von start bis end punkt die zugehörige sequenz in ein neues file zu schreiben. dh zb erste sequenz von 12-30, zweite sequenz von 35-50...usw. Ebenfalls soll im neuen file der jeweilige name aus xdom in die erste zeile mit '>' geschrieben werden.
es soll dann ungefähr so aussehen:
>name1
ggdfjkdjklsdf
>name2
uiorwejifndscn
...

Dies soll für die gesamten Dateien im Ordner geschehen.

Hoffe ich konnte das einigermaßen erklären.

Danke schonmal
Martina
martina
User
Beiträge: 29
Registriert: Montag 19. Januar 2009, 17:45

Hi,

also habe noch weiter versucht den Fehler bzw die Fehler zu finden und dabei festgestellt dass ein Fehler im Skript war(wahrscheinlich nicht der einzigste) . :?

Noch einmal zu meinem Problem:

Ich habe mehrere Dateien mit der Endung fasta im Ordner sowie mehrere dazu passende Dateien mit der Endung xdom.
Beide Dateien haben gemeinsame Namensanfänge zb Hubert.fasta und Hubert.xdom, Elli.fasta Elli.xdom.
Nun soll der gesamte Ordner bearbeitet werden, dh Hubert.fasta wird geöffnet und der Inhalt, nach line mit'>' in 'seq' gespeichert.
Anschließend sollen in dem gleichnamigen file Hubert.xdom die start,end und name werte benutzt werden, um in der 'seq' jeweils von start bis end punkt die zugehörige sequenz in ein neues file zu schreiben. dh zb erste sequenz von 12-30, zweite sequenz von 35-50...usw. Ebenfalls soll im neuen file der jeweilige name aus xdom in die erste zeile mit '>' geschrieben werden.
es soll dann ungefähr so aussehen:
>name1
ggdfjkdjklsdf
>name2
uiorwejifndscn
...

Dies soll für die gesamten Dateien im Ordner geschehen.

Hoffe ich konnte das einigermaßen erklären.

Danke schonmal
Martina
martina
User
Beiträge: 29
Registriert: Montag 19. Januar 2009, 17:45

Hi @ all,

hier nochmals mein Code, den ich bis jetzt versucht habe zu ändern,jedoch treten noch folgende Probleme aus:

1.Es wird die Sequenz eingelesen, gespeichert. Auch anhand des xdom-files wird
start,end herausgesucht und mittels print kann ich mir diese ausgeben lassen,jedoch
werden die Sequenzen nicht in das output file egschrieben.
2. Ebenfalls habe ich noch das Problem,dass er nachdem keine weiteren start und
stops im xdom file sind, nicht ein neues fasta-file mit neuer seuqenz aus dem ordner
nimmt,sondern immernoch die gleiche sequenz hat. Dies müßte ja etwas mit der
Beendigung der Schleife zu tun haben,würde ich denken. Habe schon hin und her
probiert,jedoch weiß ich nicht mehr was ich ändern muß, um den gewünschten Erfolg
zu erhalten :(

Wie gesagt,aber es funktioniert jedoch schon mehr als gedacht.
Nochmals mein Code,sorry :-(

Code: Alles auswählen

def sequence(file):
    seq=""
    file=open(file)
    for line in file:
        if ">" in line:
            continue
        print 'in sequence'
        print seq
        seq+=line.replace("\n","")
    return seq

def domains(fname,seq):
            output=open(fname+"._0.1.pfam.10.fa",'w')
            file=open(fname)   
            print file,"file"
            print seq ,"seq in dom"
            for line in file:
                if ">" in line:
                    continue
            print 'in domains'
            start=int(line.split()[0])
            end=int(line.split()[1])
            name=line.split()[2]
            test=seq[(start)-1:end]
            print test,"domain"
            output.write(">"+name+"\n"+test+"\n")

#main

x=os.listdir('.')

for file in x:
    if file.endswith("fasta"):
        seq=sequence(file)
        fname=file.split('.')[0]
        for fname in x:
           if fname.endswith(".xdom"):
               file=open(fname)
               domains(fname,seq)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Also in Zeile 36 überschreibst Du ja "fname", was Du in Zeile 35 angelegt hast? Was willst Du damit beabsichtigen?

Wieso testest Du das ganze nicht einfach erst einmal mit zwei Dateien? Damit wirst Du die "parsing" Probleme schneller finden. Der Rest ist doch bloßes iterieren.

Letzteres kann man doch testen (bzw. sich eine Funktion schreiben, die genau die Pärchen zusammenstellt), ohne dass die Dateien geöffnet werden müssen usw.

Wenn beides passt, montierst Du es einfach zusammen.

Evtl. könntest Du noch einmal posten, wie denn diese Dateien aufgebuat sind, also sample Dateien. Sollten diese länger sein, packe sie in paste.pocoo.org.

Ach ja, Du überschreibst das Built-in "file" - das macht hier vermutlich nichts, sollte man aber besser nicht tun!
martina
User
Beiträge: 29
Registriert: Montag 19. Januar 2009, 17:45

Hi,
habe meine Testdateien schon auf 2 begrenzt, um Fehler zu finden.

hatte das file überschrieben, da ich dachte man kann die gleiche Variable nicht doppelt verwenden?! ODer gilt dies nicht für file, da es fesgelegt ist bei Python das somit immer die jeweilige Datei gemeint ist? Dies wurde mir so angetragen, das es sonst nicht funktionieren würde,da man den vorherigen namen des files nicht mehr im Spreicher hätte? Hatte es nämlich ansonsten auch zu Beginn mit 'file' in beiden Schleifen.

Um die das jeweilige Pärchen zu finden, muß ich einfach Teile aus meinen Code verwenden,oder? Da ich ja schon die beiden passenden Pärchen versuche zu finden bzw es auch gefunden wird.

Dumme Frage,aber wie stelle ich die Files auf paste.pocoo.org.? habe so etwas noch nie gemacht. sorry.

Vielen Dank für die Hilfe
MArtina
martina
User
Beiträge: 29
Registriert: Montag 19. Januar 2009, 17:45

HAb es online gestellt,
hoffe du kannst darauf zugreifen?

http://paste.pocoo.org./show/108201/

Martina
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

martina hat geschrieben:Hi,
habe meine Testdateien schon auf 2 begrenzt, um Fehler zu finden.
Ja, aber ich würde die Probleme dennoch anders angehen! Zum Parsen zwei fest definierte Datein (+ ggf. eine neue Output Datei), zum Pärchen finden ruhig in den Original-Ordner gehen und dort Suchen.
hatte das file überschrieben, da ich dachte man kann die gleiche Variable nicht doppelt verwenden?! ODer gilt dies nicht für file, da es fesgelegt ist bei Python das somit immer die jeweilige Datei gemeint ist? Dies wurde mir so angetragen, das es sonst nicht funktionieren würde,da man den vorherigen namen des files nicht mehr im Spreicher hätte? Hatte es nämlich ansonsten auch zu Beginn mit 'file' in beiden Schleifen.
Nein, Du verstehst das falsch. Wähle für file einfach einen anderen Bezeichner! Du findest hier ...
http://docs.python.org/library/functions.html
... nämlich eine Built-in Funktion, die file() heißt! So etwas kann zu Problemen führen.
Um die das jeweilige Pärchen zu finden, muß ich einfach Teile aus meinen Code verwenden,oder? Da ich ja schon die beiden passenden Pärchen versuche zu finden bzw es auch gefunden wird.
k.A. - ich habe mir diesen Code nicht so genau angeguckt - aber es sieht nicht grad sauber aus! Klappt es denn? Wenn Du das nur mit 2 Dateien testest, sagt das ja nicht grad viel darüber aus ;-)
Dumme Frage,aber wie stelle ich die Files auf paste.pocoo.org.? habe so etwas noch nie gemacht. sorry.
Du siehst doch ein großes Eingabefeld. Dort kopierst Du Deinen Code / Datei usw. rein. Darunter hast Du noch eine Auswahlbox, mit der Du ggf. das Highlighting einstellen kannst (z.B. bei Python Quelltest). Wenn Du das Markup nicht kennst, dann ist "Text" (voreingestellt!) die richtige Wahl. Danach klickst Du auf "paste".

So schwer ist das doch nicht ;-)
Antworten