Mein Script - Euere Verbesserungsvorschläge/Kommentare

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
Benutzeravatar
newbie_needs_help
User
Beiträge: 18
Registriert: Donnerstag 18. Mai 2006, 08:33

Hallo ihr da draußen!

Meine kleine Vorgeschichte, ich komme aus der Bioinformatik und arbeite daher intensiv mit Datenbanken und Scripten. Die ganze Zeit nutzte ich Perl um meine Ideen umzusetzen, doch um mich nicht ganz in Perl fest zu beißen erlerne ich nebenbei Python.

Falls ihr Zeit habt, dann schaut euch doch bitte mein unten aufgeführtes Script an und gebt Kommentare und/oder Verbesserungsvorschläge ab, freue mich über jede noch so kleine Zeile!

Was ist der Hintergrund hinter diesem Script?
Wir analysieren eine Gruppe von Genen und deren Promotoren (Gene: Einheit die essentielle Information für Lebewesen enthält; Promoter: An- und Ausschalter von Genen, ein Gen kann mehrere Promotoren haben), die wir in zwei Gruppen unterteilen und zwar in die Gruppe der in „tumor-assoziierten“ und „normalen“ Gene (die Zuordnung, ob ein Gen tumor-assoziiert ist oder nicht, legt die Tabelle cancer_gene fest, ist ein Gen in dieser Tabelle aufgelistet so gehört es zu der Gruppe „tumor-assoziiert“, falls nicht zu der Gruppe der „normalen“ Gene). Dabei interessiert uns die relative Häufigkeit von allen möglichen Promoterclustern in beiden Gruppen. Ein kleines Beispiel um ein Promotercluster zu verdeutlichen:
Das Gen ‚GEN1’ hat ‚PRO1, PRO2, PRO3’ und das Gen ‚GEN2’ hat ‚PRO1, PRO3, PRO4’ als Promotoren. Es ergeben sich nun folgende mögliche Promotercluster:

Code: Alles auswählen

GEN1: PRO1-PRO2, PRO1-PRO3, PRO2-PRO3
GEN2: PRO1-PRO3, PRO1-PRO4, PRO3-PRO4
In der weiteren Analyse interessiert nur noch was für Promotorencluster zu welcher Gruppe gehört. Wenn GEN1 und GEN2 in unterschiedlichen Gruppen wären würde die Ausgabe für unser kleines ‚Genset’ lauten:

Code: Alles auswählen

tumor-assoziert:
PRO1-PRO2	1
PRO1-PRO3	1
PRO2-PRO3	1
normal:
PRO1-PRO3	1
PRO1-PRO4	1
PRO3-PRO4	1
Falls sie aber eine gemeinsamen Gruppe angehören:

Code: Alles auswählen

 
Gruppenname:
PRO1-PRO2	1
PRO1-PRO3	2
PRO2-PRO3	1
PRO1-PRO4	1
PRO3-PRO4	1


Nun mein Script was diese Aufgabe erfüllt, aber ist es die Musterlösung? Mein Modul standard ermöglicht mir die DB_Verbindung. Der Teil wo ich die DB-Info aus den Tabellen lese habe ich auskommentiert und frei erfundene Dictionaries erzeugt, so kann das Script auch bei euch laufen und ihr könnt damit experimentieren.

Code: Alles auswählen

#! /usr/bin/python2.4 -w

## import standard,sys

## standard.header()

## cursor = standard.dbconnection_localhost()
## if cursor == 'false':
##    print "database connection failed!"
##    sys.exit()


## START ##
## exits_tumor_association ##
def exits_tumor_association(gene):
    if TUMOR.has_key(gene):
        return 'true'
    else:
        return 'false'
## END ##

## START ##
## do_analysis ##
def do_analysis(Promoters, DIC):
    Flag = {}
    for promoter_a in Promoters:
        Flag[promoter_a] = 0 
        for promoter_b in Promoters:
            if Flag.has_key(promoter_b):
                t = 0
            else:
                cluster = promoter_a + ' - ' + promoter_b
                if DIC.has_key(cluster):
                    counter = DIC[cluster] + 1
                    DIC[cluster] = counter
                else:
                    DIC[cluster] = 1
    return DIC

    
## END ##


## # get a list of tumor associated genes from database and save them in dictionary TUMOR
## sql = "SELECT DISTINCT ensembl_id FROM cancer_gene WHERE ensembl_id IS NOT NULL"
## cursor.execute(sql)
## result = cursor.fetchall()

## TUMOR = {}
## for column in result:
##     gene = column[0]
##     TUMOR[gene] = 0

## get a list of genes and their corresponding promoters
## sql = "SELECT DISTINCT ensembl_gene, signalname FROM ps_signals_processed 
## WHERE ensembl_gene = 'ENSG00000160714' OR ensembl_gene = 'ENSG00000001461' OR ensembl_gene = 'ENSG00000078403' 
## OR ensembl_gene = 'ENSG00000138363'"
## sql = "SELECT DISTINCT ensembl_gene, signalname FROM ps_signals_processed"
## cursor.execute(sql)
## result = cursor.fetchall()
## result.sort()

## CLUSTER = {}
## for gene, promoter in result:
##     if CLUSTER.has_key(gene):
##         Temp = CLUSTER[gene]
##         Temp.append(promoter)
##         CLUSTER[gene]=Temp
##     else:
##         CLUSTER[gene]=[promoter]


# defining a dictionary of tumor-associated genes
TUMOR = {}
TUMOR['A']=0
TUMOR['B']=0
TUMOR['C']=0

# defining a dictionary with gene and corresponding promoter information
CLUSTER = {}
CLUSTER['A'] = ['a','b','c']    # a - b, a - c, b - c
CLUSTER['B'] = ['a','d','e']    # a - d, a - e, d - e
CLUSTER['C'] = ['a','e','f']    # a - e, c - f, e - f
CLUSTER['D'] = ['a','b']
CLUSTER['E'] = ['a','b','e','f']
CLUSTER['F'] = ['c','d']
CLUSTER['G'] = ['e','f','g']
CLUSTER['H'] = ['b','g']

TUMOR_CLUSTER = {}
NORMAL_CLUSTER = {}
for gene in CLUSTER:
    Promoters = CLUSTER[gene]
    Promoters.sort()
    
    # checking if actual gene can be assigned to tumor associated genes
    if exits_tumor_association(gene) == 'true':
        do_analysis(Promoters, TUMOR_CLUSTER)

    # if it is not associated with tumor we baptized those genes normal genes
    else:
        do_analysis(Promoters, NORMAL_CLUSTER)

# print content of tumor-associated dictionary to stdout
print "#"*10, " Analysis of tumor associated genes ", "#"*10
for cluster in TUMOR_CLUSTER:
    print cluster, TUMOR_CLUSTER[cluster]

# print content of normal dictionary to stdout
print "#"*10, " Analysis of normal genes ", "#"*10
for cluster in NORMAL_CLUSTER:
    print cluster, NORMAL_CLUSTER[cluster]
[/code]
Zuletzt geändert von newbie_needs_help am Freitag 10. November 2006, 13:43, insgesamt 2-mal geändert.
[img]http://www.danasoft.com/sig/newbieneedshelp.jpg[/img]
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:


GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Na, wenn Du Dir schon die Mühe machen willst, dann schreibe doch Deine Kommentare in docstrings um und streiche die auskommentierten Zeilen. Das macht es für uns alle lesbarer und für Dich später (wegen der docstrings) besser und einfacher nachvollziehbar.

Das ist zwar ein kleines Skript, aber - auf den ersten Blick - nicht schlecht für den Anfang. (Habe mal etwas ähnliches für Prokaryoten geschrieben.) Damit solche Skripte so richtig leistungsfähig werden, ist es besser man arbeitet objektorientiert und bastelt sich eine Klasse für Gene. Du kannst gerne auf ein Werk meines Anfangs zurückgreifen (ist entweder völlig unbrauchbar oder mittlerweile in eine Publikation eingeflossen).

Außerdem: Kennst Du BioPython? Könnte interessant für Dich sein.

So, und für mehr habe ich gerade keine Zeit, aber es finden sich sicher noch Leute Deinen Code zu besprechen.

Gruß,
Christian
BlackJack

Die erste Zeile enthält ein Leerzeichen zuviel, zwischen '!' und dem Programmpfad darf keines sein.

Anstelle von ``d.has_key(k)`` würde ich eher `k in d` schreiben. Das ist kürzer, geringfügig schneller und funktioniert auch mit anderen Containerobjekten wie `set()` oder `list()` und eigenen typen, die die `__contains__()` Methode implementieren.

Die `exits_tumor_association()` ist wahrscheinlich falsch geschrieben und überflüssig. Die Methode `dict.has_key()` bzw. der ``in`` Operator liefern schon `True` oder `False` zurück. Aus der Stelle wo Du die Funktion benutzt kannst Du also einfach folgendes machen:

Code: Alles auswählen

    if gene in TUMOR:
        do_analysis(Promoters, TUMOR_CLUSTER)
Dann hat die jetzt überflüssige Funktion auf `TUMOR` zugegriffen, was ausserhalb der Funktion definiert ist. Solche Abhängigkeiten vermeidet man besser. Was eine Funktion benötigt, sollte als Argument übergeben werden.

Auf Modulebene sollte so wenig Code wie möglich stehen. Wenn man den Hauptcode in eine Funktion schreibt, dann kann man das Modul interaktiv importieren und einzelne Funktionen ausprobieren/testen ohne das das Programm ausgeführt wird. Ob ein Modul als Programm ausgeführt oder nur import wurde erkennt man am Inhalt von `__name__`. Wenn das Modul import wurde, dann ist der Name an den Modulnamen gebunden, sonst an '__main__'. Deswegen sieht man bei Programmen am Ende fast immer:

Code: Alles auswählen

if __name__ == '__main__':
    main()
Zu `do_analysis`: Für `Flag` kannst Du ein `set()` nehmen. Dich interessiert ja nur ob so ein Promoter schon mal gesehen wurde. Der Zweig mit dem ``t = 0`` hat gar keinen Einfluss auf das Ergebnis, den kannst Du also einfach weglassen und die ``if``-Bedingung negieren. Das zählen von Clustern in einem Dictionary geht mit der `get()` Methode etwas einfacher und mit dem Rückgabewert machst Du nichts, das ``return`` kann man also weglassen. Bleibt folgendes übrig:

Code: Alles auswählen

def do_analysis(promoters, dic):
    flags = set()
    for promoter_a in promoters:
        flags.add(promoter_a)
        for promoter_b in promoters:
            if promoter_b not in flags:
                cluster = promoter_a + ' - ' + promoter_b
                dic[cluster] = dic.get(cluster, 0) + 1
Für `TUMOR` kann man so wie's da steht auch `dict.fromkeys()` benutzen:

Code: Alles auswählen

In [44]: dict.fromkeys('ABC', 0)
Out[44]: {'A': 0, 'C': 0, 'B': 0}
`CLUSTER` hätte man auch so mit Werten füllen können (nur das Du auch mal `dict()` als Konstruktor gesehen hast):

Code: Alles auswählen

    CLUSTER = dict((('A', ['a','b','c']),
                    ('B', ['a','d','e']),
                    ('C', ['a','e','f']),
                    ('D', ['a','b']),
                    ('E', ['a','b','e','f']),
                    ('F', ['c','d']),
                    ('G', ['e','f','g']),
                    ('H', ['b','g'])))
Man kann bei Dictionaries auch über Paare von (Schlüssel, Wert) iterieren, dann spart man sich eine extra Zuweisung:

Code: Alles auswählen

    for gene, promoters in CLUSTER.iteritems():
        promoters.sort()
        if gene in TUMOR:
            # ...
        #...
Das kannst Du auch bei der Ausgabe benutzen.
Benutzeravatar
newbie_needs_help
User
Beiträge: 18
Registriert: Donnerstag 18. Mai 2006, 08:33

vielen Dank für eure Hilfe!!
[img]http://www.danasoft.com/sig/newbieneedshelp.jpg[/img]
Neandertaler
User
Beiträge: 4
Registriert: Donnerstag 19. Oktober 2006, 10:34
Wohnort: Erkrath

newbie_needs_help hat geschrieben:vielen Dank für eure Hilfe!!
Hi, kannst Du vielleicht noch denn Kommentar in Zeile 55 nachträglich umbrechen? Dadurch ist bei mir der ganze Thread total breit und umstaendlich zu lesen.

Gruss
Oliver

Edit: Ich seh grad ist bei mir nur beim Konqueror so. Beim Mozilla hab ich einen Scrollbalken.
Wie kann ich wissen was ich denke bevor ich höre was ich sage...?
Benutzeravatar
newbie_needs_help
User
Beiträge: 18
Registriert: Donnerstag 18. Mai 2006, 08:33

Hi, habe deine nachricht eben erst gelesen.

ich habe es die besagte zeile bearbeitet
[img]http://www.danasoft.com/sig/newbieneedshelp.jpg[/img]
Antworten