Domanda:
Come convertire in modo sicuro ed efficiente un sottoinsieme di bam in fastq?
Kamil S Jaron
2017-07-26 16:54:47 UTC
view on stackexchange narkive permalink

Domanda

Come posso estrarre le letture da un file bam (prodotto da bwa-mem ) in fastq dato un elenco di sequenze di riferimento da filtrare?

Potenziali difficoltà

  • mantenere l'orientamento FR delle letture di fine coppia (in bam tutte le sequenze sono sequenze di riferimento)
  • mantenendo le letture R1 e R2
  • mantenendo i punteggi di qualità nella stessa codifica dell'originale fastq (punteggi phred di illumina predefiniti nel mio caso)
  • bam can essere (ana di solito è) ordinato per coordinate

Quasi ci sono soluzioni

  1. soluzione perl di Sujai in blobology fa esattamente l'opposto: ottenere letture da un elenco di riferimenti (quindi potrei semplicemente invertire l'elenco). Lo svantaggio è che lo script restituisce un file fq interleaved; richiede nomi univoci di compagni, altrimenti le informazioni R1 / R2 vengono perse.

  2. samtools + grep tutti da file fastq

creare un elenco di nomi di lettura che non si associano a scaffold filtrati. (cut estrarrà solo i nomi letti, uniq comprimerà i nomi di lettura delle coppie se sono uguali). Quindi grep legge i nomi dai file fastq e rimuove il separatore tra gli hit

  samtools view foo.bam | grep -vf list_of_scaffols_filter \ | cut -f 1 | uniq > list_of_reads_to_keepgrep -A 3 -f list_of_reads_to_keep foo_R1.fq | grep -v "^ - $" > foo_R1_filtered_bash.fqgrep -A 3 -f list_of_reads_to_keep foo_R2.fq | grep -v "^ - $" > foo_R1_filtered_bash.fq  
  1. filter bam & picard tools

Oppure I potrei fare solo la parte di filtraggio e usare Picard-tools (Picard.SamToFastq), ma come al solito evito java il più possibile. Immagino che

  samtools view foo.bam | grep -vf list_of_scaffols_filter \ | java -jar picard.jar SamToFastq INPUT = / dev / stdin \ FASTQ = foo_R1_filtered_bash.fq SECOND_END_FASTQ = foo_R2_filtered_bash.fq  

La prima soluzione non funziona davvero per me poiché non voglio rinominare tutte le letture nel file bam e voglio mantenere le informazioni R1 / R2 (poiché R1 e R2 hanno profili di errore diversi). Entrambe le soluzioni 2 e 3 le trovo un po 'goffe e non sono sicuro che siano generali, potrei avere un comportamento imprevisto se una delle letture è mappata per secondo non lo è ... Entrambe si basano sullo stesso passaggio di filtraggio.

Mi stavo chiedendo quale fosse una soluzione pysam. Immagino che sarà molto più lento, ma almeno sarà molto più chiaro e forse più generale. Qualcosa di simile a Converti file Bam in file Fasta: c'è una soluzione pysam per fasta (non fastq), quasi lì ...

Storia

Ho genoma di riferimento molto frammentato. Alcuni scaffold sono troppo piccoli per lavorare, e alcuni di loro sono contaminanti (identificati utilizzando blobtools). Voglio separare le letture che vengono mappate a diversi gruppi per separare contaminanti, scaffold brevi e scaffold che verranno utilizzati per l'analisi a valle. Il motivo è che se rimappiamo tutte le letture a riferimento filtrato (0,7 - 0,8 del genoma originale), la maggior parte di esse (0,95 - 0,99) troverà comunque un posto dove mappano, quindi ci sono 0,2 - 0,3 di letture fuori luogo che ovviamente dovrà influire sull'analisi a valle, come l'identificazione di varianti.

Questa idea di filtraggio è basata sulla logica che se la regione genomica duplicata filtrata conterrà alcune piccole differenze, attireranno le loro letture (e se le filtro le faccio migliorerà la definizione delle varianti) e se saranno esattamente gli stessi, verranno assegnate letture casuali, quindi non c'è nulla di male nel farlo.

Cosa vuoi fare se solo una lettura in una coppia si mappa su uno scaffold / contig che vuoi escludere? Onestamente, chiamerei semplicemente sort il file BAM e scriverò un po 'di python per eseguire la conversione e il filtro, ma sono solo io che sono pigro.
Non sono ancora sicuro, ma immagino che sia meglio mantenere tutte le coppie in cui almeno una delle coppie si associa a qualsiasi scaffold non filtrato.In effetti, se R1 / 2 ha gli stessi nomi, è esattamente così che è la soluzione 2 si comporterà. Se i nomi saranno diversi, filtrerò un numero diverso di letture R1 e R2.
Due risposte:
Devon Ryan
2017-07-26 18:13:32 UTC
view on stackexchange narkive permalink

Non sono a conoscenza di alcun programma preimpostato per farlo, quindi ne ho scritto uno per te. Questo richiederà un file BAM con qualsiasi ordine e produrrà file fastq gzipped correttamente ordinati con il filtro come richiesto. Internamente, questo itera su tutte le voci nel file BAM (ignorando le voci secondarie / supplementari e quelle in cui entrambi gli accoppiamenti sono mappati all'elenco dei filtri), memorizza la sequenza / qualità / lettura correttamente orientata in un buffer, quindi scarica quel buffer entrata nel disco una volta trovato l'accoppiamento. Questo dovrebbe essere ragionevolmente performante (ehi, è Python, per non aspettarti troppo), anche se se ti capita di avere file BAM indicizzati, allora si potrebbe pensare a come renderlo più veloce.

Controlla l'output, poiché ho eseguito solo un test.

Sei stato 3 minuti più veloce e il tuo codice sembra molto più bello. Lo proverò ... Grazie mille.
L'unico vero vantaggio del mio codice è che evita di saltare nel file BAM alla ricerca di compagni e che il file BAM non deve essere ordinato. Se hai file ordinati, penso che sarebbe più veloce creare un elenco di contig che non sono esclusi, aggiungere "*" a quello e quindi iterare su di esso come nel mio programma. Risparmierebbe più tempo.
Kamil S Jaron
2017-07-26 18:17:23 UTC
view on stackexchange narkive permalink

Ok, ho scritto un parser pysam / BioPython un po 'bruto che usa l'indice di bam per ottenere il corretto ordine della coppia di lettura per i file R1 / R2 e il flag bit per bit. Non dovrebbe essere troppo difficile aggiungere ora regole di filtraggio più sofisticate.

  #! / Usr / bin / env python3 # 1. arg - file bam indicizzato # 2. arg - elenco di intestazioni da filter # 3. arg - nome pattern per l'output readsimport osimport sysimport pysamfrom Bio import SeqIO, Seq, SeqRecordsamfile = pysam.AlignmentFile (sys.argv [1], "rb") header_set = set (line.strip () per line in open (sys.argv [2])) base = sys.argv [3] out_R1 = base + 'R1_filtered.fq'out_R2 = base +' R2_filtered.fq'con open (out_R1, mode = 'w') come R1, open (out_R2, mode = 'w') as R2: for entry in samfile: if entry.is_read1 and not entry.reference_name in header_set: # pait pair entry_R2 = samfile.mate (entry) # fai un po 'di ginnastica in sequenza con R1 seq_R1 = Seq.Seq (entry.seq) if entry.is_reverse: seq_R1 = seq_R1.reverse_complement () # fai un po 'di ginnastica in sequenza con R2 seq_R2 = Seq.Seq (entry_R2.seq) if entry_R2.is_reverse : seq_R2 = seq_R2.reverse_complement () R1.write ('@' + entry.qname + '\ n' + str (seq_R1) + '\ n + \ n' + entry.qqual + '\ n') R2.write ( '@' + entry_R2.qname + '\ n' + str (seq_R2) + '\ n + \ n' + entry_R2.qqual + '\ n') samfile.close ()  

Ci sono alcune brutte parti, sentiti libero di renderlo più carino.



Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...