Questão:
Como htslib / samtools acessa campos BAM opcionais?
EB2127
2018-04-03 08:49:40 UTC
view on stackexchange narkive permalink

Estou confuso sobre como várias bibliotecas de software lidam com campos opcionais em um BAM:

Com base na especificação BAM, existem 11 campos obrigatórios para um BAM:

  QNAME, FLAG, RNAME, POS, MAPQ, CIGAR, RNEXT, PNEXT, TLEN, SEQ, QUAL  

Os arquivos BAM de hoje normalmente têm muitos campos opcionais também, que deve estar no formato TAG: TYPE: VALUE , em que TAG é uma string de dois caracteres que corresponde a / [A-Za-z] [A-Za-z0-9] / e TYPE são uma única letra com distinção entre maiúsculas e minúsculas que define o formato de VALUE . Cada TAG só pode aparecer uma vez em uma linha de alinhamento.

Certos BAMs podem não ter campos opcionais, enquanto outros têm vários.

Meu entendimento é que as tags opcionais podem estar em uma ordem diferente de linha para linha e, às vezes, simplesmente não existem.

Minhas perguntas:

  1. Como o htslib / samtools (por exemplo, visualização do samtools ) acessar esses campos opcionais, que diferem em número de BAM para BAM (possível linha para linha)?

    Em htslib / sam.h , uma estrutura de alinhamento BAM é definido da seguinte forma:

      / *! @typedef @abstract Estrutura para um alinhamento. @field core core information sobre o alinhamento @field l_data comprimento atual de bam1_t :: data @field m_data comprimento máximo de bam1_t :: data @field data todos os dados de comprimento variável, concatenados; estrutura: qname-cigar-seq-qual-auxtypedef struct {bam1_core_t core; int l_data; uint32_t m_data; uint8_t * data; #ifndef BAM_NO_ID uint64_t id; #endif} bam1_t;  

    e seguido por vários métodos que acessam campos BAM obrigatórios, por exemplo,

      / *! @function @abstract Pega o nome da consulta @param b ponteiro para um alinhamento @return ponteiro para a string de nome, terminado em nulo * / # define bam_get_qname (b) ((char *) (b) ->data)  
  2. Como o htslib acessa cada um dos campos opcionais, dada esta estrutura ? Mantém a ordem dos campos opcionais ou essa informação não está disponível?

  3. Quando um usuário executa htslib ou mesmo samtools view , como a linha BAM "termina", ou seja, qual estrutura de dados existe para mostrar que o BAM linha não tem mais campos opcionais e que o algoritmo deve "mover-se" para a próxima linha BAM.

Qualquer esclarecimento sobre como o código-fonte funciona neste caso é muito apreciado.

[Postado cruzado no Reddit] (https://www.reddit.com/r/bioinformatics/comments/89946w/how_does_htslibsamtools_access_optional_bam_fields)
Dois respostas:
Konrad Rudolph
2018-04-03 15:53:37 UTC
view on stackexchange narkive permalink

Como htslib acessa cada um dos campos opcionais, dada esta estrutura?

htslib usa uma macro, bam_get_aux , para este propósito. Você pode verificar o código-fonte dessa macro - ela basicamente apenas avança o ponteiro de dados do registro atual para o início dos dados opcionais, que estão depois de todos os outros dados. Mas você não deve se preocupar com isso, e apenas usar as funções exportadas relevantes para ler dados opcionais (“auxiliares”):

  • bam_aux_get retorna um ponteiro para um opcional registro, dado por seu nome de tag de dois caracteres.
  • bam_aux2 ‹C› converte o ponteiro retornado pela função anterior para o tipo real da tag opcional; aqui, ‹C› é um identificador de tipo: i para um inteiro, Z para uma sequência de caracteres terminada em zero, etc. Consulte o documentação e o arquivo htslib / sam.h para uma lista completa.

Mantém a ordem dos campos opcionais ou esta informação não está disponível ?

Desde que você não modifique os campos opcionais, a ordem é mantida, mas não especificada. Não confie no pedido !

Quando um usuário executa htslib ou mesmo samtools view , como a linha BAM "termina"

Os registros BAM armazenam um cabeçalho que contém o tamanho do registro.

@EB2127 Não, não será necessariamente uniforme. E se houver algoritmos que dependem da ordem, esses algoritmos são quebrados porque estão quebrando a especificação BAM. Como tal, * não há como * definir a ordem. Se você precisa de tags ordenadas (mas para quê ?!), você precisa armazenar o pedido dentro dos próprios dados da tag (por exemplo, prefixando os dados da tag com ordinais).
Obrigado, agradeço a ajuda. Outra pergunta: "Você pode verificar o código-fonte dessa macro - ela basicamente apenas avança o ponteiro de dados do registro atual para o início dos dados opcionais, que estão depois de todos os outros dados.". Você poderia detalhar os detalhes para isso? Isso pode me ajudar a entender melhor como essas macros funcionam. por exemplo. `bam_get_qname ()` parece estar acessando o membro 'data' de struct bam1_t, que tem a forma "qname-cigar-seq-qual-aux". Então 'bam_get_cigar ()' está avançando o ponteiro de dados do registro atual para o comprimento do nome da consulta, `core.l_qname`?
Devon Ryan
2018-04-03 14:42:06 UTC
view on stackexchange narkive permalink
  1. Em um arquivo BAM, todas as tags auxiliares (os campos opcionais aos quais você se refere) são mantidas, o que é efetivamente um campo void * , uma após a outra. Cada entrada neste campo é estruturada como dois char s armazenando o nome da tag (por exemplo, NM , seguido por um char armazenando o tipo ( por exemplo, Z ou i ), seguido pelos dados em qualquer formato apropriado ( char , float , etc ). Strings nas tags aux são NULL terminadas, então seus comprimentos não são armazenados explicitamente.
  2. Para acessar um determinado campo, htslib tem que iterar sobre todos eles, em seja qual for a ordem em que estejam armazenados, até encontrar a correta. A ordem de saída com a visualização samtools é a ordem em que são armazenados.
  3. O tamanho de * dados são armazenados como l_data , então, uma vez que acertar isso, ele saberá que o registro foi concluído.

Em relação ao ponto 1, este é um truque C padrão de conversão entre tipos de dados. Assim, embora * data seja na verdade um uint8_t * (também conhecido como uma matriz de bytes), os primeiros dois bytes de cada tag são char se o que quer que esteja depois deles (bem, depois do byte especificando o tipo) é então convertido para o tipo apropriado (seja float ou char * ou o que não). Isso provavelmente ficará mais claro se você olhar o código.

Obrigado pela ajuda; isso foi muito útil. Você poderia detalhar o número 1 um pouco mais? Ou seja, como os campos opcionais são armazenados com um tipo de ponteiro genérico?
@EB2127 Eu adicionei um pouco mais de detalhes conforme solicitado. É melhor apenas olhar para o código-fonte neste momento. Ignore as coisas do tipo `B`, uma vez que provavelmente será apenas confuso no início.


Estas perguntas e respostas foram traduzidas automaticamente do idioma inglês.O conteúdo original está disponível em stackexchange, que agradecemos pela licença cc by-sa 3.0 sob a qual é distribuído.
Loading...