Estou respondendo à pergunta 1. No entanto, como não estou familiarizado com o python, estou fornecendo uma solução javascript apenas para mostrar a lógica básica. Para tentar o código no final, você precisa instalar node.js e executá-lo com node this-script.js
.
Dado que este é um padrão muito análise
Tendo a acreditar que esta é uma análise muito rara. Eu só vi isso ser feito duas vezes. Converter o CIGAR + MD em alinhamento preenchido é complicado na codificação, pois você deve manter a sequência, o charuto e o MD sincronizados o tempo todo. O código abaixo gera duas strings de uma vez. Pode ser logicamente mais fácil gerar a referência e as strings de consulta separadamente.
Em geral, MD é mal definido. É muito difícil trabalhar com ele. Se possível, evite essa tag. Você pode fazer muitas coisas com a combinação de CIGAR e NM.
function md2pad (CIGAR, MD, SEQ) {var m, re_cigar = / (\ d +) ([MIDSHNX =]) / g, re_MD = / (\ d +) | (\ ^ [A-Za-z] +) | ([A-Za-z]) / g; var charuto = []; while ((m = re_cigar.exec (CIGAR))! = null) // analisa o CIGAR em uma matriz if (m [2]! = 'H') // não faz nada para o recorte rígido, pois não tem efeito charuto. empurre ([parseInt (m [1]), m [2]]); var k = 0, sx = '', sy = ''; // k: k-ésimo operador de charuto; x: ref; y: consulta // cx / cy: coordenada inicial de charuto [k] em ref / consulta; mx / my: início da op atual MD var cx = 0, cy = 0, mx = 0, my = 0; while ((m = re_MD.exec (MD))! = null) {if (m [2]! = null) {// exclusão da referência var len = m [2] .length - 1; // comprimento da deleção sx + = m [2] .substr (1), sy + = Array (len + 1) .join ("-"); mx + = len, cx + = len, ++ k; // consome uma exclusão D de ref} else {// cópia ou incompatibilidade var ml = m [1]! = null? parseInt (m [1]): 1; // duração desta operação MD while (k < cigar.length && charuto [k] [1]! = 'D') {var cl = charuto [k] [0], op = charuto [k] [1];
if (op == 'M' || op == 'X' || op == '=') {if (my + ml < cy + cl) {// um MD termina no meio do charuto M if ( ml > 0) {if (m [3]! = null) sx + = m [3], sy + = SEQ [my]; else sx + = SEQ.substr (my, ml), sy + = SEQ.substr (my, ml); } mx + = ml, my + = ml, ml = 0; quebrar; } else {var dl = cy + cl - my; sx + = SEQ.substr (my, dl), sy + = SEQ.substr (my, dl); cx + = cl, cy + = cl, ++ k; // consome um operador M mx + = dl, my + = dl, ml - = dl; }} else if (op == 'I') {sy + = SEQ.substr (cy, cl), sx + = Array (cl + 1) .join ("-"); cy + = cl, my + = cl, ++ k; // consumir uma inserção I para ref} else if (op == 'S') {cy + = cl, my + = cl, ++ k; // consome um soft-clipping S} senão lança Error ("MD inconsistente"); // não funciona com N} if (ml! = 0) throw Error ("MD inconsistente"); }} if (cx! = mx || cy! = my) throw Error ("MD inconsistente"); retorno [sx, sy];} var charuto = '16025H3M2I55M1D108M306H'; var MD = '7T15C24T9 ^ C0G2T6T16T3A1A7G21T17G6C1T6T5A4'; SEQ var = 'GATCACAGGCCTATCACCCTATTAATCACTCACGGGAGCTCTCCATGCATCTGGTATTTTTTCGGGGGGGGATGCACGCGATAGCATCGCGGGCCGCTGGAACCGGAGCACCCTATGTCGCAGGATCTGTCTTTGATTCCTACCTCATGCCATTATTAATCGCGCCTA'; var s = md2pad (charuto, MD, seq); console.log (s [0 ]); console.log (s [1]);