def seq_display(request, align_slug): """ Serves query display page :param request: HTTP request :param align_id: alignment pk :return:HttpResponse or HttpResponseNotAllowed object """ if request.method == 'GET': # split sequences in chunks of 80 characters align_id = Alignment.objects.get(slug=align_slug).pk alignment = consensus_add(Alignment.objects.get_alignment(align_id)) alphabets = { "Gapped(ExtendedIUPACProtein(), '-')": 'Protein', "Gapped(ExtendedIUPACDNA(), '-')": 'DNA', } alphabet = alphabets[str(alignment[0].seq.alphabet)] query_seqs = split_lines(alignment, line_length=80, split_type='sequence') return render( request, 'base/query_display.html', {'query_seqs': query_seqs, 'seq_type': alphabet, 'align_id': align_slug} ) else: return HttpResponseNotAllowed(['GET'])
def test_align_display_page_displays_correct_consensus(self): """ Tests that align_display displays the correct consensus sequence """ expected_seqs = file_to_string("spa_protein_alignment.fasta") align_expected = io.StringIO(expected_seqs) alignment = parse_fasta_alignment(align_expected) alignment = consensus_add(alignment) # get displayed sequences with self.assertHTML(self.response, "tr") as elems: seq_disp = [] for els in elems: seq_disp_line = [] for e in els.findall("td")[:-1]: if e.attrib["class"] in ["residue S0", "residue S1"]: seq_disp_line.append(e.text) if seq_disp_line: seq_disp.append(seq_disp_line) # recompose sequences cat_re_seq = [] for j in range(len(alignment) - 1, len(seq_disp), len(alignment)): re_seq = [seq_disp[j] for j in range(len(alignment) - 1, len(seq_disp), len(alignment))] cat_re_seq = [] for r in re_seq: cat_re_seq.extend(r) # check consensus cons_li = list(alignment[-1].seq) self.assertEqual(cons_li, cat_re_seq, cat_re_seq)
def test_consensus_get_returns_consensus_to_alignment(self): """ Tests that consensus_add function returns correct default consensus """ alignment = self.alignment cons_seq = AlignInfo.SummaryInfo(alignment).gap_consensus() cons_got = consensus_add(alignment)[-1] self.assertEqual(cons_seq, cons_got.seq, cons_got.seq) self.assertEqual("consensus 70%", cons_got.id, cons_got.id)
def test_annotate_returns_correct_default_consensus_annotation(self): """ Tests that consensus is correctly annotated for display """ exp_annot = [0, 1, 0, 1, 0, 1, 0, 0, 0, 0] alignment = consensus_add(self.alignment_a) annot_alignment = annotate(alignment) self.assertEqual( exp_annot, annot_alignment[-1].letter_annotations["eq"], annot_alignment[-1].letter_annotations["eq"] )
def align_display(request, align_slug): """ serves alignment display page :param request: HTTP request :param align_id: alignment pk :return: HttpResponse object """ if request.method == 'GET': align_id = Alignment.objects.get(slug=align_slug).pk alignment_fetch = Alignment.objects.get_alignment(align_id) alignment = consensus_add(alignment_fetch) alignment = annotate(alignment) # get longest id for id display width id_lengths = [len(a.id) for a in alignment] id_lengths.sort(reverse=True) id_width = id_lengths[0] + 2 # split sequences in lines of 80 characters seq_lines = split_lines(alignment, line_length=80, split_type='alignment') # split lines in blocks of 10 characters block_length = 10 seqs_blocks = [ [ [ ls.id, [ zip( ls.letter_annotations['eq'][j:j + block_length], list(ls[j:j + block_length]) ) for j in range(0, len(ls), block_length) ] ] for ls in ln] for ln in seq_lines ] align = { 'align_seqs': seqs_blocks, } r = render( request, 'base/align_display.html', {'align': align, 'id_width': id_width * .6, 'total_width': (id_width + 80) * .5} ) return r
def test_annotate_returns_correct_sequence_annotations(self): """ Tests that sequences are correctly annotated for display """ exp_annot = [ [0, 1, 0, 1, 0, 1, 0, 0, 0, 0], [0, 1, 0, 1, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 1, 0, 0, 0, 0], [0, 1, 0, 1, 0, 1, 0, 0, 0, 0], ] alignment = consensus_add(self.alignment_a) annot_alignment = annotate(alignment) for i, e in enumerate(exp_annot): self.assertEqual( e, annot_alignment[i].letter_annotations["eq"], annot_alignment[i].letter_annotations["eq"] )
def test_align_display_renders_correct_color_classes(self): """ Tests that align_display assigns the correct color classes (residue S0 or residue S1) to the residues """ expected_seqs = file_to_string("spa_protein_alignment.fasta") align_expected = io.StringIO(expected_seqs) alignment = parse_fasta_alignment(align_expected) alignment = consensus_add(alignment) alignment = annotate(alignment) # get displayed sequences with self.assertHTML(self.response, "tr") as elems: seq_disp = [] for els in elems: seq_disp_line = [] for e in els.findall("td")[:-1]: if e.attrib["class"] in ["residue S0", "residue S1"]: seq_disp_line.append(e.attrib["class"]) if seq_disp_line: seq_disp.append(seq_disp_line) # recompose sequences re_seqs = [] cat_re_seq = [] for i in range(0, len(alignment)): for j in range(i, len(seq_disp), len(alignment)): re_seq = [seq_disp[j] for j in range(i, len(seq_disp), len(alignment))] cat_re_seq = [] for r in re_seq: cat_re_seq.extend(r) re_seqs.append(cat_re_seq) # check color classes for i, al in enumerate(alignment): al_li = ["residue S%s" % a for a in al.letter_annotations["eq"]] self.assertEqual(al_li, re_seqs[i], re_seqs)