SuffixTree

Original English version: http://cs.au.dk/~mailund/suffix_tree.html

Denne modulen bryter en C-implementering av et suffiks-tre.

Pythonbindingene er hovedsakelig ment for eksperimentering med suffiks-trebaserte algoritmer. Følgelig er de ikke spesielt rom- eller tidseffektive, men i stedet lett uttrekkbare.

Bruk


Å bygge et enkelt suffiks-tre – et suffiks-tre med en enkelt streng – importer SuffixTree-klassen og ordne det med strengen:

from suffix_tree import SuffixTree
stree = SuffixTree('mississippi')

Du kan nå krysse treet gjennom en rekke iteratorer: leaves, innerNodes, preOrderNodes, og postOrderNodes, som krysser alle blader, alle indre knuter, alle knutepunkter i henholdsvis pre- og postordre:

>>> for l in stree.leaves:
...     print l.pathLabel
...
mississippi$
ississippi$
issippi$
ippi$
i$
ssissippi$
ssippi$
sissippi$
sippi$
ppi$
pi$
$

Til mer tilgang til lavnivå er rotnoden tilgjengelig som stree.root egenskap.

Strengenparameteren til suffiks-treet er tilgjengelig gjennom string eiendom:

>>> stree.string[2:4]
'ss'

Et generalisert suffiks-tre – et suffiks-tre som representerer et sett med strenger – kan konstrueres ved hjelp av GeneralisedSuffixTree-klassen:

from suffix_tree import GeneralisedSuffixTree
stree = GeneralisedSuffixTree(['mississippi','sippissi'])

I tillegg til funksjonaliteten til det enkle suffiks-treet har det generaliserte suffiks-treet en funksjon for å trekke ut alle delte delstrenger av settet av strenger eller alle delte delstrenger av en gitt minimal lengde

for shared in st.sharedSubstrings():
    print '-'*70
    for seq,start,stop in shared:
        print seq, '['+str(start)+':'+str(stop)+']',
        print sequences[seq][start:stop],
        print sequences[seq][:start]+'|'+sequences[seq][start:stop]+\
              '|'+sequences[seq][stop:]
print '='*70

for shared in st.sharedSubstrings(2):
    print '-'*70
    for seq,start,stop in shared:
        print seq, '['+str(start)+':'+str(stop)+']',
        print sequences[seq][start:stop],
        print sequences[seq][:start]+'|'+sequences[seq][start:stop]+\
              '|'+sequences[seq][stop:]
print '='*70

Nodene har attributter for banemerket (pathLabel) — etiketten på banen fra roten til noden – for kantmerketiketten (edgeLabel) — etiketten på kanten fra foreldre til node – for å få tilgang til første og siste barn i noden (firstChild og lastChild), til tilgang til venstre og høyre søsken (prev og next) og noen flere. Se onlinehjelpen for flere detaljer.

Hver node har en tilknyttet ordbok, noe som gjør det enkelt å annotere noder for algoritmisk prototyping, som illustrert nedenfor i et stykke kode hentet fra implementeringen av det generelle suffiks-treet:

for n in self.postOrderNodes:
    if n.isLeaf:
        seq,idx = self._translateIndex(n.index)
        n.pathIndices = [(seq, idx)]
        n.sequences = [seq]
    else:
        pathIndices = [] ; sequences = []
        c = n.firstChild
        while c is not None:
            pathIndices += c.pathIndices
            sequences += c.sequences
            c = c.next

        seqsInSubtree = {}
        for s in sequences:
            seqsInSubtree[s] = 1

        n.pathIndices = pathIndices
        n.sequences = [s for s in seqsInSubtree]

Her blir noderne annotert med par sekvens ganger indeks for de enkelte sekvensene i det generaliserte suffiks-treet, og med settet av sekvenser representert i noder-subtrærne.

Det generaliserte treet er bygget ved hjelp av en sammenkobling av alle inngangsstrengene. Banemerkene er derfor ikke akkurat etikettene du forventer, men ved hjelp av merknaden kan de forventede etikettene hentes ut.

Et siste advarselsvarsel: Pythonbindingene trenger virkelig den sykliske søppelsamleren for å kunne rydde opp suffikstrær. Træret må referere til noderne, så de vil ikke bli slettet med annotasjonen, og noderne må referere til treet slik at det ikke vil forsvinne mens manuset refererer til noden.

Dessverre har jeg ikke vært i stand til å gjøre det arbeidet. Siden vi virkelig trenger å rydde opp trærne når vi prototype, har jeg valgt følgende løsning: treet refererer til noderne, men noderne refererer ikke til treet. Det er derfor skriptforfatterens ansvar å sørge for at treet ikke blir søppel samlet mens nodene i treet er referert. Alternativet vil føre til at trær aldri blir søppel samlet. Jeg håper å fikse dette problemet snart.

Installasjon

For å installere pythonbindingen for suffiks trær, last ned kildekoden og pakke ut den (ved bruk av tar xzf suffix_tree-a.b.c.tar.gz, hvor a.b.c er versjonsnummeret). Kjør deretter installasjonsskriptet:

python setup.py install

Dette vil bygge C-biblioteket og pythonbindingene, og installere modulen.

Se python setup.py --help til flere detaljer.

En eldre versjon (versjon 1.0 og 1.1), også nedlastbar fra her, var basert på en suffiks tre gjennomføring av Dotan Tsadoc og Shlomo Yona. Hvis du bruker denne versjonen, må du være oppmerksom på at API er litt endret.

Ta kontakt med

Thomas Mailund<[email protected]>, Bioinformatikk forskningssenter, Aarhus Universitet.