Pregunta:
Divida FASTQ y BAM coincidente en trozos iguales
Scott Gigante
2017-08-17 07:33:01 UTC
view on stackexchange narkive permalink

Estoy ejecutando un análisis lento en sentido descendente en un gran conjunto de lecturas de nanoporos (aproximadamente 3 millones) y me gustaría dividirlas en trozos más pequeños, ejecutar el análisis en paralelo masivo y luego recombinarlo. Originalmente, simplemente dividí el FASTQ en partes, realineé cada parte y luego fusioné la salida, pero aquí me gustaría usar una alineación existente para poder comparar los resultados con los análisis existentes (es decir, las alineaciones deben ser las mismas).

¿Cómo puedo dividir eficientemente un archivo FASTQ y un archivo BAM dando la alineación del archivo FASTA en fragmentos, asegurando que todas las lecturas en el fragmento 1 de FASTQ estén en el fragmento 1 de BAM, viceversa y así sucesivamente?

Mi FASTQ es de aproximadamente 45 GB y mi BAM es de 33 GB, por lo que preferiría evitar almacenar uno de los dos archivos en la memoria si es posible.

EDITAR: Aquí hay un pseudocódigo de exactamente qué Estoy tratando de hacer:

  # input: in.bam, in.fastq, chunk_sizei <- 0for fastq_read in in.fastq: bam_read <- extract fastq_read.read_name from in.bam n <- i modulo chunk_size escribo fastq_read en out.n.fastq escribo bam_read en out.n.bam i <- i + 1  

Podría intercambiar lo anterior para iterar a través del bam y recupérelo del fastq si le resulta más fácil.

¿Su archivo BAM ya tiene el mismo orden que los archivos fastq (algunos alineadores lo producen de forma predeterminada)? Si ese no es el caso, prácticamente te quedas con (1) ordenar archivos o (2) hash de nombres leídos.
Desafortunadamente, no están en el mismo orden y, además, algunas lecturas existen varias veces en el BAM (alineaciones complementarias) y un puñado de lecturas no existen en absoluto en el BAM.
Vaya, tu única opción es algo como lo que publicó Michael Hall entonces.
One responder:
Michael Hall
2017-08-17 12:33:11 UTC
view on stackexchange narkive permalink

Hmm, es difícil pensar en una forma súper eficiente de hacer esto (asumiendo que los archivos no están ordenados de la misma manera; si lo están, entonces toda esta respuesta es básicamente redundante). Y también asumiendo que los identificadores de lectura para ambos archivos no son una intersección perfecta.

En la parte superior de mi cabeza, probablemente quiera construir un conjunto de identificadores de lectura para el archivo fastq y otro para el bam. Algo de código Python para comenzar con eso:

  import pysamimport itertoolsdef get_read_id_fastq (ref_path): "" "Extrae los identificadores de lectura de un archivo fastq." "" Read_ids = set () con open ( ref_path, 'r') as ref: for line in ref: if line.startswith ('@'): # es decir, si la línea es encabezado # divida la línea en espacios, tome el primer elemento, elimine @ read_id = line.split ( '') [0] .replace ('@', '') read_ids.add (read_id) return read_idsdef get_read_id_bam (ref_path): "" "Extrae los identificadores de lectura de un archivo BAM." "" Read_ids = set () con pysam.AlignmentFile (ref_path, 'r', ignore_truncation = True) como ref: para leer en ref: # query_name es el nombre de la plantilla de consulta read_ids.add (read.query_name) return read_idsfastq_ids = get_read_id_fastq (fastq_path) bam_ids = get_read_amid_bam 

Luego, tome la intersección de estos dos conjuntos y esos son sus identificadores de lectura comunes.

  common_ids = fastq_ids & bam_ids  

La siguiente parte será un poco más complicada. Tendrá que recorrer cada archivo de uno en uno. Sugeriría que para el primero que recorra, cree un diccionario en ejecución con la identificación de lectura que se escribió como clave y el 'número de mandril' en el que se escribió como valor. Podría crear un ciclo para el tamaño de su fragmento para administrar esto de manera efectiva

  chunk_cycle = itertools.chain (* zip (range (chunk_size) * len (common_ids))) write_idx = {}  

La siguiente parte probablemente requerirá que dediques algunos momentos difíciles para que funcione. Pondré un pseudocódigo aproximado para darte una idea.

  para la línea en el archivo: read_id = # get line read_id si read_id en common_ids: chunk_num = chunk_cycle.next () write_idx [read_id] = chunk_num file_to_write_to = 'out. {}. bam'.format (chunk_num) # abre este archivo o escribe en él si ya está abierto  

Cuando vayas a hacer el siguiente archivo cuando encuentra un id de lectura en el conjunto común, busca su valor en write_idx y esto le dará el número de fragmento para escribir.

Las lecturas no estarán exactamente en el mismo orden entre los dos archivos, pero podría ordenar más tarde si lo necesita (¿no está seguro de que importe?).

Espero que esto ayude. Lo siento, no pude darte más, pero espero que esto te dé una ventaja.

¡Gracias! De hecho, no necesitaría la primera parte, ya que todas las lecturas del BAM provienen del FASTQ. Si hay registros FASTQ que no existen en el BAM, no me importa.
Actualización: cualquiera que esté interesado puede obtener mi implementación de esta solución en https://github.com/scottgigante/nanopore-scripts/blob/master/split_bam_and_fasta.py


Esta pregunta y respuesta fue traducida automáticamente del idioma inglés.El contenido original está disponible en stackexchange, a quien agradecemos la licencia cc by-sa 3.0 bajo la que se distribuye.
Loading...