Einer Variable eine Funktion zuweisen?

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
würmchen
User
Beiträge: 255
Registriert: Mittwoch 7. November 2007, 14:17

Hallo Leute,
ich schreibe gerade PDB Dateien aus einer Datenbank. Das sind letztendlich Atomkoordinaten von Proteinen.

Im Moment dauert eine Datei mit 680kb (rund 10000 Zeilen) etwa 20 Sekunden, was mir für die geringe Datenmenge recht lange vor kommt.

Ich habe jetzt den Code überprüft und hier und da ein paar logging aufrufe gemacht, weil ich erst vermutete das das lesen aus der Datenbank so lange dauert, aber das ist innerhalb einer Sekunde abgeschlossen.

Ich habe dann die Loops weiter untersucht und stelle fest, das in der atomLoop geprüft wird ob es sich um ein Wasserstoff handelt, wenn in dem Objekt Wasserstoffe ausgegeben werden sollen.
Im Klartext heißt das, es wird 10000 mal geprüft, ob jedes Atom ein Wasserstoff ist, wenn nein, wird es geschrieben.

Dies kann aber ausgewählt werden, nicht immer muss ein Wasserstoff herausgefiltert werden. Ich bin jetzt am überlegen wie ich das am besten beschleunige.

Meine Idee ist zwei Funktionen zu schreiben,

Code: Alles auswählen

def atomLoopWithHydrogens()
    'will use every atom'
    pass 

atomLoopWithoutHydrogens()
    'will not print hydrogens'
    pass.
Und dann vor dem ausführen testen, welche der Beiden Funktionen genutzt werden soll

Code: Alles auswählen

if hydrogens:
    atomLoop = atomLoopWithHydrogens
Ich will also die atomLoop die schon im Code benutzt wird durch eine der beiden neuen Schleifen ersetzen.

Wollte fragen ob das eine saubere Lösung ist, oder wie man sowas besser macht.

Muss dazusagen, es sind ein paar solcher Abfragen, letztendlich 18 Stück, die nicht immer geprüft werden müssen und die ich mir so meist sparen könnte.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

tu es.
Aber achte darauf, in Code selbst dann echtes Python zu schreiben ;)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Übrigens, für so eine Diagnose ist es oftmals nützlich den Profiler zu verwenden.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Fabian Kochem
User
Beiträge: 36
Registriert: Mittwoch 5. April 2006, 14:11
Wohnort: Köln

Leonidas hat geschrieben:Übrigens, für so eine Diagnose ist es oftmals nützlich den Profiler zu verwenden.
... welchen du im "pdb"-Modul findest.
BlackJack

@würmchen: Ich wäre da nicht so schnell mit dem Rat das zu tun, weil die Funktionsnamen suggerieren, dass der Code darin bis auf den Test sehr ähnlich ist.

Falls dem so ist, solltest Du versuchen wirklich nur die Unterschiede heraus zu ziehen. So in der Richtung:

Code: Alles auswählen

def is_hydrogen(atom):
    # ...


def is_from_krypton(atom):
    # ...


def process_atoms(atoms, filters=()):
    for atom in atoms:
        if all(f(atom) for f in filters):
            print atom
Da kannst Du dann gar keine Filterfunktionen, oder eben beliebige Kombinationen von Testfunktionen übergeben, die ein `atom` hernehmen und einen Wahrheitswert liefern.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Fabian Kochem hat geschrieben:... welchen du im "pdb"-Modul findest.
Das ist der Python Debugger, kein Profiler. Python bringt eigentlich drei Profiler mit: cProfile (empfohlen), profile und hotshot die eben unter diesen Namen als Module existieren.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
würmchen
User
Beiträge: 255
Registriert: Mittwoch 7. November 2007, 14:17

BlackJack hat geschrieben:@würmchen: Ich wäre da nicht so schnell mit dem Rat das zu tun, weil die Funktionsnamen suggerieren, dass der Code darin bis auf den Test sehr ähnlich ist.

Falls dem so ist, solltest Du versuchen wirklich nur die Unterschiede heraus zu ziehen. So in der Richtung:

Code: Alles auswählen

def is_hydrogen(atom):
    # ...


def is_from_krypton(atom):
    # ...


def process_atoms(atoms, filters=()):
    for atom in atoms:
        if all(f(atom) for f in filters):
            print atom
Da kannst Du dann gar keine Filterfunktionen, oder eben beliebige Kombinationen von Testfunktionen übergeben, die ein `atom` hernehmen und einen Wahrheitswert liefern.
Sehr interessantes Konstrukt, filters würde ich dann die funktionen in einem tuple übergeben? also praktisch so, oder?

Code: Alles auswählen

process_atoms(list_with_atoms, (funktion1,funktion2,funktion3,))
Oder habe ich das dann falsch verstanden?


@rest, danke für den Hinweis mit dem Profiler, hab mir das Kapitel 25 aus der lib doku mal ausgedruckt und werde es jetzt durcharbeiten...
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

würmchen, Du schreibst einen PDB-Parser? Also als Programmierübung vielleicht interessant. Ansonsten gibt es im PDB-Modul von biopython natürlich einen Parser. Und in openbabel gibt es das auch - inkl. Pythoninterface. Und ich will nichts ausschließen, daß es noch mehr frei verfügbar gibt (möglicherweise pymol? - habe aber nichts finden können auf die Schnelle). Jedenfalls, denke ich, daß mit openbabel auch eine sehr schnelle Lösung vorliegt, die sehr mächtig ist.

HTH,
Christian

edit: biopython-PDB bietet leider keine Abfrage, welches Atom gerade angesprochen wird. In meiner Software überprüfe ich, ob ein Atom in einer best. Liste auftaucht und handele dementsprechend. Z. B. so

Code: Alles auswählen

elif pofr_restraint == 'hydrogen':
            logging.info("    hydrogen-flag set, only hydrogen atoms will be considered")
            atoms = [atom for atom in atoms if atom.id in hydrogenidentifiers]
, was Du hier findest: http://svn.origo.ethz.ch/viewvc/sas-rig ... iew=markup
würmchen
User
Beiträge: 255
Registriert: Mittwoch 7. November 2007, 14:17

CM hat geschrieben:würmchen, Du schreibst einen PDB-Parser? Also als Programmierübung vielleicht interessant. Ansonsten gibt es im PDB-Modul von biopython natürlich einen Parser. Und in openbabel gibt es das auch - inkl. Pythoninterface. Und ich will nichts ausschließen, daß es noch mehr frei verfügbar gibt (möglicherweise pymol? - habe aber nichts finden können auf die Schnelle). Jedenfalls, denke ich, daß mit openbabel auch eine sehr schnelle Lösung vorliegt, die sehr mächtig ist.

HTH,
Christian
Hi Christian,
danke für den Hinweis, mir ist bekannt dass es von biopython einen Parser gibt, nur war der auf den ersten Blick für mein Vorhaben zu komplex. Ich hab mich dann entschlossen, den von der Gruppe geschrieben Parser etwas zu verbessern und meinen Bedürfnissen anzupassen.
Ich beziehe die Informationen für die Atome aus einer MySQL Datenbank und bin mir nicht sicher wie ich die anderen Parser da mit reinstricken kann. Aber vielleicht sollte ich doch auch mal ein paar Minuten damit verbringen die Möglichkeiten mit diesen Tools abzuschätzen.

Mir geht es letztendlich um Geschwindigkeit, und ich finde es nicht vertretbar, auf eine PDB Datei eine Minute zu warten ;-)
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Ich hoffe Du hast die Strukturen in der Datenbank liegen und nicht die einzelnen Atome - das wäre nämlich reichlich umständlich. Ansonsten frage ich mich wie groß Deine Moleküle sind. Ich schaffe es 1.7 MDa in wenigen Sekunden zu parsen. Und z. B. für das Löschen der H-Atome brauche ich in dem Fall 15-20 Sekunden - aber das mache im Programm nur einmal und damit ist die Sache gegessen. Deshalb habe ich da auch nicht optimiert.

Nebenbei: biopython steigt gerade auf numpy um (von mir stammt die Anpassung für das PDB.Vektor-Modul - ich weiß also wovon ich rede ;-). Jetzt ist also die Zeit alle Fehler, die Dir auffallen dem Team von biopython zu melden. Wäre schön.

Gruß,
Christian
würmchen
User
Beiträge: 255
Registriert: Mittwoch 7. November 2007, 14:17

nein, die atome liegen einzeln in der Datenbank.
Ich weiß das das umständlich ist, desshalb hat die Arbeitsgruppe einen eigenen Parser entwickelt.
Es ist aber für bestimmte Anwendungen nützlich, auf jedes einzelne Atom zugreifen zu können... Dafür ist diese Datenbank entwickelt worden, für die ich ein Interface Programmiere...
Im Moment sind etwas mehr als 400 000 000 000 Atome in der Datenbank...
Wobei das Auslesen der Datenbank das geringste Problem ist...
Das geht in weniger als einer Sekunde...
Antworten