Seite 1 von 1
Komprimierung von DNA Sequenz
Verfasst: Freitag 1. Januar 2021, 19:03
von Zauberer
Hi,
ich lese gerade das Programmierbuch Algorhitme in Python und es geht um triviale Programmierung. Da steht ein Code den ich nicht kapiere. Also ich weiß halt nicht wie man ihn verwendet und welche Bedeutung sentinel und self.bit_string: int 1 hat. self.bit_string<<=2 verstehe ich teilweise. Also muss man für den Parameter gene, eine gene sequenz angeben und dann wird diese in integer oder in bitstringsdargestellt
class CompressedGene:
def __init__(self, gene: str) -> None:
self._compress(gene)
def _compress(self, gene: str) -> None:
self.bit_string = 1 # start with sentinal
for nucleotide in gene.upper():
self.bit_string <<= 2 # shift left 2 mits
if nucleotide == "A":
self.bit_string |= 0b00
elif nucleotide == "C":
self.bit_string |= 0b01
elif nucleotide == "G":
self.bit_string |= 0b10
elif nucleotide == "T":
self.bit_string |= 0b11
else:
raise ValueError("Invalid Nucleotide: {}".format(nucleotide))
def decompress(self) -> str:
gene: str = ""
for i in range(0, self.bit_string.bit_length() - 1, 2): # -1 to exclude sentinal
bits: int = self.bit_string >> i & 0b11 # get 2 relevant bits
if bits == 0b00:
gene += "A"
elif bits == 0b01:
gene += "C"
elif bits == 0b10:
gene += "G"
elif bits == 0b11:
gene += "T"
else:
raise ValueError("Invalide bits: ()".format(bits))
return gene[::-1] #reverse string
def __str__(self) -> str:
return self.decompress()
Ich habe den Code von github übernommen und dann die _compress funktion angewandt, ohne Erfolg. Leider bekomme ich den FehlerCode
NameError: name '_compress' is not defined. Ich kann nicht verstehen, weshalb dieser Fehler auftaucht, weil die Funktion definiert ist.
if __name__ =="__main__":
from sys import getsizeof
original: str = " ccgacatgag acagttaggt atcgtcgaga gttacaagct aaaacgagca aaattt tttttgcgcgc gcgc"
print("Original: {} Byte".format(getsizeof(original)))
print(_compress(original))
Wäre echt cool, wenn mir da einer helfen könnte
Mit freundlichen Grüßen
Re: Komprimierung von DNA Sequenz
Verfasst: Freitag 1. Januar 2021, 19:47
von __blackjack__
@Zauberer: Die Funktion ist nicht definiert weil es so eine Funktion nicht gibt. Es gibt dort eine Methode in einer Klasse die so heisst. Die sollte man aber nicht aufrufen, denn der führende Unterstrich bedeutet in Python „Finger weg, das ist ein Implementierungsdetail“.
`getsizeof()` ist auch nicht wirklich sinnvoll. Das hängt von zu vielen Implementierungsdedails ab.
Es werden zu viele Typannoationen gemacht. Wenn man einem Namen direkt einen Wert von dem Typ zuweist ist die Typannotation sinnfrei, denn sowohl der Leser als auch die Typprüfung die man verwendet, brauchen diese redundante Information nicht.
Re: Komprimierung von DNA Sequenz
Verfasst: Samstag 2. Januar 2021, 16:44
von Zauberer
__blackjack__
Das compress keine Funktion ist verstehe ich nicht. Ich habe mir auch die Erklärung für Methoden auf python-kurs.eu angesehen, leider verstehe ich sie nicht komplett. Ich dachte, dass alles was hinter def steht eine Funktion ist. Könnten Sie mir vielleicht erklären, was diese Methode macht oder wofür sie steht? Ich verstehe leider auch nicht was mit sentinel gemeint ist, weil die Erklärung eine ganz andere im Internet ist. Da steht, dass es ein Wert ist mit der man eine While oder For loop Schleife abbricht. In der Methode compress steht, dass sentinel mit eins beginnt. Ich kann mir das nicht erklären. Wird dann bei dem Wert abgebrochen? ICh versetehe auch nicht wie ein bitstring eine eins darstellen kann. Ist ein Bit nicht 0 und 1? Da steht in der Methode, dass der bitstring um 2 nach links verschoben wird. Also immer mit zwei 00? Und wenn A 0b00 ist, wird es dann zu 0b0000? und ist ein Bit string so etwas wie "1001001110001" beispielsweise oder ist mit dem Bit string gmeint, das so was wie "ACGTGGTCGT" in einen string aus bit konvertiert wird? Und( -> None:) bedeutet dies, dass keine Konvertierung stattfindet?
#Definition von Methoden
#Eine Methode unterscheidet sich äußerlich nur in zwei Aspekten von von einer Funktion:
#Sie ist eine Funktion, die innerhalb einer class-Definition definiert ist.
#Der erste Parameter einer Methode ist immer eine Referenz self auf die Instanz, von der sie aufgerufen wird.
#Der Parameter self erscheint nur bei der Definition einer Methode. Beim Aufruf wird er nicht angegeben.
#Beispiel mit Methode:
#class Konto(object):
# def ueberweisen(self, ziel, betrag):
# pass
#def einzahlen(self, betrag):
# pass
#def auszahlen(self, betrag):
# pass
#def kontostand(self):
# pass
#Konstruktor
Der erste Parameter ist immer eine Referenz self auf die Instanz, von der sie aufgerufen wird. Was ist hier die Instanz?
Danke dass sie mir helfen
Re: Komprimierung von DNA Sequenz
Verfasst: Samstag 2. Januar 2021, 16:54
von Sirius3
Eine Funktion wird mit def definiert, aber wenn eine Funktion in einem Klassen-Block steht, dann ist das ein Methode. Und um Methoden aufzurufen, braucht man eine Instanz der Klasse.
In Bit ist 0 oder 1, ein Bitstring ist hier einfach eine Folge von Bits, profan gesagt, eine Zahl.
Ein Sentinel ist einfach nur eine Markierung, nämlich hier, die Markierung, wie viele Bits der Bitstring hat.
Was Typannotationen sind, ließt Du am besten in der Dokumentation nach. Das -> None bedeutet nur, dass die Funktion einen Rückgabewert hat.
Die Umwandlung ist reichlich kompliziert, dafür gibt es Wörterbücher, statt langer if-Kaskaden. Ob dafür überhaupt eine Klasse nötig ist, bezweifle ich:
Code: Alles auswählen
NUCLEOTIDES = "ACGT"
NUCLEOTIDE_TO_BITS = dict(zip(NUCLEOTIDES, range(len(NUCLEOTIDES))))
def compress_gene(gene):
bits = 1 # start with sentinal
for nucleotide in gene.upper():
try:
bits = (bits << 2) | NUCLEOTIDE_TO_BITS[nucleotide]
except KeyError:
raise ValueError("Invalid Nucleotide: {}".format(nucleotide))
return bits
def decompress_gene(gene_bits):
gene = []
for i in reversed(range(0, gene_bits.bit_length(), 2)):
bits = (gene_bits >> i) & 0b11
gene.append(NUCLEOTIDES[bits])
return "".join(gene)
original = " ccgacatgag acagttaggt atcgtcgaga gttacaagct aaaacgagca aaattt tttttgcgcgc gcgc"
gene_bits = compress_gene(original.replace(" ",""))
print(decompress_gene(gene_bits))
Re: Komprimierung von DNA Sequenz
Verfasst: Samstag 2. Januar 2021, 17:37
von __blackjack__
Das dekodieren könnte ein bisschen ineffizient werden bei längeren Sequenzen. Da finde ich den Ansatz im Original besser, die Bits immer von unten zu nehmen und bei jedem Schritt um zwei Bits zu verschieben.
Ich würde am Ende noch ein ``assert bits == 1`` anfügen um zu sehen ob der Sentinel-Wert noch da ist. Das erklärt den vielleicht auch ein kleines bisschen.
Re: Komprimierung von DNA Sequenz
Verfasst: Samstag 2. Januar 2021, 17:52
von Sirius3
@__blackjack__: das dachte ich im ersten Moment auch, aber das Original rechnet immer mit dem gesamten Bit-String, da wird nichts verschoben. Ich entschied mich dann aber für Klarheit und Kürze.
Re: Komprimierung von DNA Sequenz
Verfasst: Samstag 2. Januar 2021, 18:00
von Zauberer
Ich habe da noch ein paar Fragen, was sind Generics, Typehints, Callables, Callback Funktionen, und welche Bedeutung hat deklarieren. Und welchen Unterschied hat deklarieren von definieren? Ich lese diese Begriffe sehr häfig ohne eine richtige Beschreibung zu finden. Meist ist es auf Englisch und für mich ist es sehr schwer eine deutsche Übersetzung zu erschließen.
Re: Komprimierung von DNA Sequenz
Verfasst: Samstag 2. Januar 2021, 19:34
von __blackjack__
@Zauberer: Typehints sind Typhinweise im Quelltext, die von Software ausgewertet werden können, und die der Leser lesen kann. In Python heissen die auch Typannotationen und sind Teil der Syntax. Python selbst macht damit aber nichts, das heisst wenn man die schreibt, sollte man ganz dringend auch eine Software anwenden, die die auswertet und prüft, damit man am Ende keine falschen Hinweise im Quelltext stehen hat die den Leser verwirren und zu Fehlern verleiten.
Das ist alles ziemlich kompliziert, insbesondere wenn Du dann auch noch mit Generics anfängst, und man braucht das nicht wirklich. Generic braucht man beispielsweise, wenn man variable Typvariablen für einen Datentyp ”deklarieren” möchte.
Callables sind einfach Objekte die man aufrufen kann. Also alles was eine `__call__()`-Methode hat. Funktionen, Klassen, und Methoden beispielsweise.
Callbacks sind aufrufbare Objekte die man irgendwo als Argument übergibt oder Attribut setzt, die dann von anderem Code irgendwann aufgerufen werden. Zum Beispiel in einer GUI etwas das aufgerufen wird, wenn der Benutzer ein Schaltfläche anklickt.