Exemplo n.º 1
0
 def get_helical_box(self):
     residuelist = Residue.objects.filter(
         protein_conformation__protein__entry_name=str(
             self)).prefetch_related('protein_segment',
                                     'display_generic_number',
                                     'generic_number')
     return DrawHelixBox(residuelist, self.get_protein_class(), str(self))
Exemplo n.º 2
0
def detail(request, slug):
    # get family
    pf = ProteinFamily.objects.get(slug=slug)

    # get family list
    ppf = pf
    families = [ppf.name]
    while ppf.parent.parent:
        families.append(ppf.parent.name)
        ppf = ppf.parent
    families.reverse()

    # number of proteins
    proteins = Protein.objects.filter(family__slug__startswith=pf.slug,
                                      sequence_type__slug='wt')
    no_of_proteins = proteins.count()
    no_of_human_proteins = Protein.objects.filter(
        family__slug__startswith=pf.slug,
        species__id=1,
        sequence_type__slug='wt').count()

    # get structures of this family
    structures = Structure.objects.filter(
        protein_conformation__protein__parent__family__slug__startswith=slug
    ).order_by('-representative',
               'resolution').prefetch_related('pdb_code__web_resource')

    mutations = MutationExperiment.objects.filter(protein__in=proteins)

    # fetch proteins and segments
    proteins = Protein.objects.filter(family__slug__startswith=slug,
                                      sequence_type__slug='wt',
                                      species__id=1)
    segments = ProteinSegment.objects.filter(partial=False)

    # create an alignment object
    a = Alignment()

    # load data into the alignment
    a.load_proteins(proteins)
    a.load_segments(segments)

    # build the alignment data matrix
    a.build_alignment()

    # calculate consensus sequence + amino acid and feature frequency
    a.calculate_statistics()

    HelixBox = DrawHelixBox(a.full_consensus, 'Class A', str('test'))
    SnakePlot = DrawSnakePlot(a.full_consensus, 'Class A', str('test'))

    try:
        pc = ProteinConformation.objects.get(
            protein__family__slug=slug,
            protein__sequence_type__slug='consensus')
    except ProteinConformation.DoesNotExist:
        pc = ProteinConformation.objects.get(protein__family__slug=slug,
                                             protein__species_id=1,
                                             protein__sequence_type__slug='wt')

    residues = Residue.objects.filter(
        protein_conformation=pc).order_by('sequence_number').prefetch_related(
            'protein_segment', 'generic_number', 'display_generic_number')

    # process residues and return them in chunks of 10
    # this is done for easier scaling on smaller screens
    chunk_size = 10
    r_chunks = []
    r_buffer = []
    last_segment = False
    border = False
    title_cell_skip = 0
    for i, r in enumerate(residues):
        # title of segment to be written out for the first residue in each segment
        segment_title = False

        # keep track of last residues segment (for marking borders)
        if r.protein_segment.slug != last_segment:
            last_segment = r.protein_segment.slug
            border = True

        # if on a border, is there room to write out the title? If not, write title in next chunk
        if i == 0 or (border and len(last_segment) <=
                      (chunk_size - i % chunk_size)):
            segment_title = True
            border = False
            title_cell_skip += len(
                last_segment
            )  # skip cells following title (which has colspan > 1)

        if i and i % chunk_size == 0:
            r_chunks.append(r_buffer)
            r_buffer = []

        r_buffer.append((r, segment_title, title_cell_skip))

        # update cell skip counter
        if title_cell_skip > 0:
            title_cell_skip -= 1
    if r_buffer:
        r_chunks.append(r_buffer)

    context = {
        'pf': pf,
        'families': families,
        'structures': structures,
        'no_of_proteins': no_of_proteins,
        'no_of_human_proteins': no_of_human_proteins,
        'a': a,
        'HelixBox': HelixBox,
        'SnakePlot': SnakePlot,
        'mutations': mutations,
        'r_chunks': r_chunks,
        'chunk_size': chunk_size
    }

    return render(request, 'family/family_detail.html', context)
Exemplo n.º 3
0
def render_variants(request,
                    protein=None,
                    family=None,
                    download=None,
                    receptor_class=None,
                    gn=None,
                    aa=None,
                    **response_kwargs):

    simple_selection = request.session.get('selection', False)
    proteins = []
    if protein:  # if protein static page
        proteins.append(Protein.objects.get(entry_name=protein.lower()))

    target_type = 'protein'
    # flatten the selection into individual proteins
    if simple_selection:
        for target in simple_selection.targets:
            if target.type == 'protein':
                proteins.append(target.item)
            elif target.type == 'family':
                target_type = 'family'
                familyname = target.item
                # species filter
                species_list = []
                for species in simple_selection.species:
                    species_list.append(species.item)

                # annotation filter
                protein_source_list = []
                for protein_source in simple_selection.annotation:
                    protein_source_list.append(protein_source.item)

                if species_list:
                    family_proteins = Protein.objects.filter(
                        family__slug__startswith=target.item.slug,
                        species__in=(species_list),
                        source__in=(protein_source_list)).select_related(
                            'residue_numbering_scheme', 'species')
                else:
                    family_proteins = Protein.objects.filter(
                        family__slug__startswith=target.item.slug,
                        source__in=(protein_source_list)).select_related(
                            'residue_numbering_scheme', 'species')

                for fp in family_proteins:
                    proteins.append(fp)

    NMs = NaturalMutations.objects.filter(
        Q(protein__in=proteins)).prefetch_related(
            'residue__generic_number', 'residue__display_generic_number',
            'residue__protein_segment', 'protein')
    ptms = PTMs.objects.filter(
        Q(protein__in=proteins)).prefetch_related('residue')
    ptms_dict = {}

    ## MICROSWITCHES
    micro_switches_rset = ResiduePositionSet.objects.get(name="Microswitches")
    ms_label = []
    for residue in micro_switches_rset.residue_position.all():
        ms_label.append(residue.label)

    ms_object = Residue.objects.filter(
        protein_conformation__protein=proteins[0],
        generic_number__label__in=ms_label)
    ms_sequence_numbers = []
    for ms in ms_object:
        ms_sequence_numbers.append(ms.sequence_number)

    ## SODIUM POCKET
    sodium_pocket_rset = ResiduePositionSet.objects.get(name="Sodium pocket")
    sp_label = []
    for residue in sodium_pocket_rset.residue_position.all():
        sp_label.append(residue.label)

    sp_object = Residue.objects.filter(
        protein_conformation__protein=proteins[0],
        generic_number__label__in=ms_label)
    sp_sequence_numbers = []
    for sp in sp_object:
        sp_sequence_numbers.append(sp.sequence_number)

    for ptm in ptms:
        ptms_dict[ptm.residue.sequence_number] = ptm.modification

    ## G PROTEIN INTERACTION POSITIONS
    # THIS SHOULD BE CLASS SPECIFIC (different set)
    rset = ResiduePositionSet.objects.get(name='Signalling protein pocket')
    gprotein_generic_set = []
    for residue in rset.residue_position.all():
        gprotein_generic_set.append(residue.label)

    ### GET LB INTERACTION DATA
    # get also ortholog proteins, which might have been crystallised to extract
    # interaction data also from those
    if protein:
        orthologs = Protein.objects.filter(
            family__slug=proteins[0].family.slug, sequence_type__slug='wt')
    else:
        orthologs = Protein.objects.filter(
            family__slug__startswith=proteins[0].family.slug,
            sequence_type__slug='wt')

    interactions = ResidueFragmentInteraction.objects.filter(
        structure_ligand_pair__structure__protein_conformation__protein__parent__in
        =orthologs,
        structure_ligand_pair__annotated=True).exclude(
            interaction_type__type='hidden').all()
    interaction_data = {}
    for interaction in interactions:
        if interaction.rotamer.residue.generic_number:
            sequence_number = interaction.rotamer.residue.sequence_number
            # sequence_number = lookup[interaction.rotamer.residue.generic_number.label]
            label = interaction.rotamer.residue.generic_number.label
            aa = interaction.rotamer.residue.amino_acid
            interactiontype = interaction.interaction_type.name
            if sequence_number not in interaction_data:
                interaction_data[sequence_number] = []
            if interactiontype not in interaction_data[sequence_number]:
                interaction_data[sequence_number].append(interactiontype)

    if target_type == 'family':
        pc = ProteinConformation.objects.get(
            protein__family__name=familyname,
            protein__sequence_type__slug='consensus')
        residuelist = Residue.objects.filter(protein_conformation=pc).order_by(
            'sequence_number').prefetch_related('protein_segment',
                                                'generic_number',
                                                'display_generic_number')
    else:
        residuelist = Residue.objects.filter(
            protein_conformation__protein=proteins[0]).prefetch_related(
                'protein_segment', 'display_generic_number', 'generic_number')

    jsondata = {}
    for NM in NMs:
        functional_annotation = ''
        SN = NM.residue.sequence_number
        if NM.residue.generic_number:
            GN = NM.residue.generic_number.label
        else:
            GN = ''
        if SN in sp_sequence_numbers:
            functional_annotation += 'SodiumPocket '
        if SN in ms_sequence_numbers:
            functional_annotation += 'MicroSwitch '
        if SN in ptms_dict:
            functional_annotation += 'PTM (' + ptms_dict[SN] + ') '
        if SN in interaction_data:
            functional_annotation += 'LB (' + ', '.join(
                interaction_data[SN]) + ') '
        if GN in gprotein_generic_set:
            functional_annotation += 'GP (contact) '

        ms_type = NM.type
        if ms_type == 'missense':
            effect = 'deleterious' if NM.sift_score <= 0.05 or NM.polyphen_score >= 0.1 else 'tolerated'
            color = '#e30e0e' if NM.sift_score <= 0.05 or NM.polyphen_score >= 0.1 else '#70c070'
        else:
            effect = 'deleterious'
            color = '#575c9d'
        # account for multiple mutations at this position!
        NM.functional_annotation = functional_annotation
        # print(NM.functional_annotation)
        jsondata[SN] = [
            NM.amino_acid, NM.allele_frequency, NM.allele_count,
            NM.allele_number, NM.number_homozygotes, NM.type, effect, color,
            functional_annotation
        ]

    natural_mutation_list = {}
    max_snp_pos = 1
    for NM in NMs:
        if NM.residue.generic_number:
            if NM.residue.generic_number.label in natural_mutation_list:
                natural_mutation_list[
                    NM.residue.generic_number.label]['val'] += 1
                if not str(NM.amino_acid) in natural_mutation_list[
                        NM.residue.generic_number.label]['AA']:
                    natural_mutation_list[NM.residue.generic_number.label][
                        'AA'] = natural_mutation_list[
                            NM.residue.generic_number.label]['AA'] + str(
                                NM.amino_acid) + ' '

                if natural_mutation_list[
                        NM.residue.generic_number.label]['val'] > max_snp_pos:
                    max_snp_pos = natural_mutation_list[
                        NM.residue.generic_number.label]['val']
            else:
                natural_mutation_list[NM.residue.generic_number.label] = {
                    'val': 1,
                    'AA': NM.amino_acid + ' '
                }

    jsondata_natural_mutations = {}

    for r in residuelist:
        if r.generic_number:
            if r.generic_number.label in natural_mutation_list:
                jsondata_natural_mutations[
                    r.sequence_number] = natural_mutation_list[
                        r.generic_number.label]

    jsondata_natural_mutations['color'] = linear_gradient(start_hex="#c79494",
                                                          finish_hex="#c40100",
                                                          n=max_snp_pos)
    # jsondata_cancer_mutations['color'] = linear_gradient(start_hex="#d8baff", finish_hex="#422d65", n=max_cancer_pos)
    # jsondata_disease_mutations['color'] = linear_gradient(start_hex="#ffa1b1", finish_hex="#6e000b", n=max_disease_pos)
    #
    SnakePlot = DrawSnakePlot(residuelist, "Class A", protein, nobuttons=1)
    HelixBox = DrawHelixBox(residuelist, 'Class A', protein, nobuttons=1)

    # EXCEL TABLE EXPORT
    if download:

        data = []
        for r in NMs:
            values = r.__dict__
            data.append(values)
        headers = [
            'type', 'amino_acid', 'allele_count', 'allele_number',
            'allele_frequency', 'polyphen_score', 'sift_score',
            'number_homozygotes', 'functional_annotation'
        ]

        # EXCEL SOLUTION
        output = BytesIO()
        workbook = xlsxwriter.Workbook(output)
        worksheet = workbook.add_worksheet()

        col = 0
        for h in headers:
            worksheet.write(0, col, h)
            col += 1
        row = 1
        for d in data:
            col = 0
            for h in headers:
                worksheet.write(row, col, str(d[h]))
                col += 1
            row += 1
        workbook.close()
        output.seek(0)
        xlsx_data = output.read()

        response = HttpResponse(
            xlsx_data,
            content_type=
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        )
        response[
            'Content-Disposition'] = 'attachment; filename=GPCRdb_' + proteins[
                0].entry_name + '_variant_data.xlsx'  # % 'mutations'
        return response

    return render(
        request, 'browser.html', {
            'mutations': NMs,
            'type': target_type,
            'HelixBox': HelixBox,
            'SnakePlot': SnakePlot,
            'receptor': str(proteins[0].entry_name),
            'mutations_pos_list': json.dumps(jsondata),
            'natural_mutations_pos_list':
            json.dumps(jsondata_natural_mutations)
        })
Exemplo n.º 4
0
def detail(request, slug):
    # get family
    pf = ProteinFamily.objects.get(slug=slug)

    # get family list
    ppf = pf
    families = [ppf.name]
    while ppf.parent.parent:
        families.append(ppf.parent.name)
        ppf = ppf.parent
    families.reverse()

    # number of proteins
    proteins = Protein.objects.filter(family__slug__startswith=pf.slug,
                                      sequence_type__slug='wt')
    no_of_proteins = proteins.count()
    no_of_human_proteins = Protein.objects.filter(
        family__slug__startswith=pf.slug,
        species__id=1,
        sequence_type__slug='wt').count()
    list_proteins = list(proteins.values_list('pk', flat=True))

    # get structures of this family
    structures = Structure.objects.filter(
        protein_conformation__protein__parent__family__slug__startswith=slug
    ).order_by('-representative',
               'resolution').prefetch_related('pdb_code__web_resource')

    mutations = MutationExperiment.objects.filter(
        protein__in=proteins).prefetch_related('residue__generic_number',
                                               'exp_qual', 'ligand')

    interactions = ResidueFragmentInteraction.objects.filter(
        structure_ligand_pair__structure__protein_conformation__protein__parent__in
        =proteins,
        structure_ligand_pair__annotated=True).exclude(
            interaction_type__type='hidden').order_by(
                'rotamer__residue__sequence_number')
    interaction_list = {}
    for interaction in interactions:
        if interaction.rotamer.residue.generic_number:
            gn = interaction.rotamer.residue.generic_number.label
            aa = interaction.rotamer.residue.amino_acid
            interactiontype = interaction.interaction_type.name
            if gn not in interaction_list:
                interaction_list[gn] = []
            interaction_list[gn].append([aa, interactiontype])

    ## Variants
    NMs = NaturalMutations.objects.filter(
        protein__in=proteins).prefetch_related('residue__generic_number')

    natural_mutation_list = {}
    max_snp_pos = 1
    for NM in NMs:
        if NM.residue.generic_number:
            if NM.residue.generic_number.label in natural_mutation_list:
                natural_mutation_list[
                    NM.residue.generic_number.label]['val'] += 1
                if not str(NM.amino_acid) in natural_mutation_list[
                        NM.residue.generic_number.label]['AA']:
                    natural_mutation_list[NM.residue.generic_number.label][
                        'AA'] = natural_mutation_list[
                            NM.residue.generic_number.label]['AA'] + str(
                                NM.amino_acid) + ' '

                if natural_mutation_list[
                        NM.residue.generic_number.label]['val'] > max_snp_pos:
                    max_snp_pos = natural_mutation_list[
                        NM.residue.generic_number.label]['val']
            else:
                natural_mutation_list[NM.residue.generic_number.label] = {
                    'val': 1,
                    'AA': NM.amino_acid + ' '
                }

    ## PTMs
    ptms = PTMs.objects.filter(
        protein__in=proteins).prefetch_related('residue__generic_number')

    ptm_list = {}
    for ptm in ptms:
        if ptm.residue.generic_number:
            if ptm.residue.generic_number.label in ptm_list:
                ptm_list[ptm.residue.generic_number.label]['val'] += 1
                if not str(ptm.modification) in ptm_list[
                        ptm.residue.generic_number.label]['mod']:
                    ptm_list[ptm.residue.generic_number.label][
                        'mod'] = ptm_list[ptm.residue.generic_number.
                                          label]['mod'] + ', ' + str(
                                              ptm.modification)
            else:
                ptm_list[ptm.residue.generic_number.label] = {
                    'val': 1,
                    'mod': ptm.modification
                }

    # CMs = CancerMutations.objects.filter(
    #     protein__in=proteins).prefetch_related('residue__generic_number')
    #
    # cancer_mutation_list = {}
    # max_cancer_pos = 1
    # for CM in CMs:
    #     if CM.residue.generic_number:
    #         if CM.residue.generic_number.label in cancer_mutation_list:
    #             cancer_mutation_list[CM.residue.generic_number.label]['val'] += 1
    #             if not str(CM.amino_acid) in cancer_mutation_list[CM.residue.generic_number.label]['AA']:
    #                 cancer_mutation_list[CM.residue.generic_number.label]['AA'] = cancer_mutation_list[CM.residue.generic_number.label]['AA'] + str(CM.amino_acid)
    #
    #             if cancer_mutation_list[CM.residue.generic_number.label]['val'] > max_cancer_pos:
    #                 max_cancer_pos = cancer_mutation_list[CM.residue.generic_number.label]['val']
    #         else:
    #             cancer_mutation_list[CM.residue.generic_number.label] = {'val':1, 'AA': CM.amino_acid}
    #
    # DMs = DiseaseMutations.objects.filter(
    #     protein__in=proteins).prefetch_related('residue__generic_number')

    # disease_mutation_list = {}
    # max_disease_pos = 1
    # for DM in DMs:
    #     if DM.residue.generic_number:
    #         if DM.residue.generic_number.label in disease_mutation_list:
    #             disease_mutation_list[DM.residue.generic_number.label]['val'] += 1
    #             if not str(DM.amino_acid) in disease_mutation_list[DM.residue.generic_number.label]['AA']:
    #                 disease_mutation_list[DM.residue.generic_number.label]['AA'] = disease_mutation_list[DM.residue.generic_number.label]['AA'] + str(DM.amino_acid)
    #
    #             if disease_mutation_list[DM.residue.generic_number.label]['val'] > max_cancer_pos:
    #                 max_cancer_pos = disease_mutation_list[DM.residue.generic_number.label]['val']
    #         else:
    #             disease_mutation_list[DM.residue.generic_number.label] = {'val':1, 'AA': DM.amino_acid}

    mutations_list = {}
    for mutation in mutations:
        if not mutation.residue.generic_number:
            continue  #cant map those without display numbers
        if mutation.residue.generic_number.label not in mutations_list:
            mutations_list[mutation.residue.generic_number.label] = []
        if mutation.ligand:
            ligand = mutation.ligand.name
        else:
            ligand = ''
        if mutation.exp_qual:
            qual = mutation.exp_qual.qual
        else:
            qual = ''
        mutations_list[mutation.residue.generic_number.label].append(
            [mutation.foldchange,
             ligand.replace("'", "\\'"), qual])

    try:
        pc = ProteinConformation.objects.get(
            protein__family__slug=slug,
            protein__sequence_type__slug='consensus')
    except ProteinConformation.DoesNotExist:
        pc = ProteinConformation.objects.get(protein__family__slug=slug,
                                             protein__species_id=1,
                                             protein__sequence_type__slug='wt')

    residues = Residue.objects.filter(
        protein_conformation=pc).order_by('sequence_number').prefetch_related(
            'protein_segment', 'generic_number', 'display_generic_number')

    jsondata = {}
    jsondata_interaction = {}
    jsondata_natural_mutations = {}
    jsondata_ptms = {}
    # jsondata_cancer_mutations = {}
    # jsondata_disease_mutations = {}
    for r in residues:
        if r.generic_number:
            if r.generic_number.label in mutations_list:
                jsondata[r.sequence_number] = [
                    mutations_list[r.generic_number.label]
                ]
            if r.generic_number.label in interaction_list:
                jsondata_interaction[r.sequence_number] = interaction_list[
                    r.generic_number.label]
            if r.generic_number.label in natural_mutation_list:
                jsondata_natural_mutations[
                    r.sequence_number] = natural_mutation_list[
                        r.generic_number.label]
            if r.generic_number.label in ptm_list:
                jsondata_ptms[r.sequence_number] = ptm_list[
                    r.generic_number.label]
            # if r.generic_number.label in cancer_mutation_list:
            # jsondata_cancer_mutations[r.sequence_number] = cancer_mutation_list[r.generic_number.label]
            # if r.generic_number.label in disease_mutation_list:
            # jsondata_disease_mutations[r.sequence_number] = disease_mutation_list[r.generic_number.label]

    jsondata_natural_mutations['color'] = linear_gradient(start_hex="#c79494",
                                                          finish_hex="#c40100",
                                                          n=max_snp_pos)
    # jsondata_cancer_mutations['color'] = linear_gradient(start_hex="#d8baff", finish_hex="#422d65", n=max_cancer_pos)
    # jsondata_disease_mutations['color'] = linear_gradient(start_hex="#ffa1b1", finish_hex="#6e000b", n=max_disease_pos)

    HelixBox = DrawHelixBox(residues, 'Class A',
                            'family_diagram_preloaded_data')
    SnakePlot = DrawSnakePlot(residues, 'Class A',
                              'family_diagram_preloaded_data')

    # process residues and return them in chunks of 10
    # this is done for easier scaling on smaller screens
    chunk_size = 10
    r_chunks = []
    r_buffer = []
    last_segment = False
    border = False
    title_cell_skip = 0
    for i, r in enumerate(residues):
        # title of segment to be written out for the first residue in each segment
        segment_title = False

        # keep track of last residues segment (for marking borders)
        if r.protein_segment.slug != last_segment:
            last_segment = r.protein_segment.slug
            border = True

        # if on a border, is there room to write out the title? If not, write title in next chunk
        if i == 0 or (border and len(last_segment) <=
                      (chunk_size - i % chunk_size)):
            segment_title = True
            border = False
            title_cell_skip += len(
                last_segment
            )  # skip cells following title (which has colspan > 1)

        if i and i % chunk_size == 0:
            r_chunks.append(r_buffer)
            r_buffer = []

        r_buffer.append((r, segment_title, title_cell_skip))

        # update cell skip counter
        if title_cell_skip > 0:
            title_cell_skip -= 1
    if r_buffer:
        r_chunks.append(r_buffer)

    context = {
        'pf': pf,
        'families': families,
        'structures': structures,
        'no_of_proteins': no_of_proteins,
        'no_of_human_proteins': no_of_human_proteins,
        'HelixBox': HelixBox,
        'SnakePlot': SnakePlot,
        'mutations': mutations,
        'r_chunks': r_chunks,
        'chunk_size': chunk_size,
        'mutations_pos_list': json.dumps(jsondata),
        'interaction_pos_list': json.dumps(jsondata_interaction),
        'natural_mutations_pos_list': json.dumps(jsondata_natural_mutations),
        'ptms_pos_list': json.dumps(jsondata_ptms)
    }  # ,'cancer_mutations_pos_list': json.dumps(jsondata_cancer_mutations), 'disease_mutations_pos_list': json.dumps(jsondata_disease_mutations)

    return render(request, 'family/family_detail.html', context)
Exemplo n.º 5
0
def detail(request, slug):
    # get family
    pf = ProteinFamily.objects.get(slug=slug)

    # get family list
    ppf = pf
    families = [ppf.name]
    while ppf.parent.parent:
        families.append(ppf.parent.name)
        ppf = ppf.parent
    families.reverse()

    # number of proteins
    proteins = Protein.objects.filter(family__slug__startswith=pf.slug,
                                      sequence_type__slug='wt')
    no_of_proteins = proteins.count()
    no_of_human_proteins = Protein.objects.filter(
        family__slug__startswith=pf.slug,
        species__id=1,
        sequence_type__slug='wt').count()
    list_proteins = list(proteins.values_list('pk', flat=True))

    # get structures of this family
    structures = Structure.objects.filter(
        protein_conformation__protein__parent__family__slug__startswith=slug
    ).order_by('-representative',
               'resolution').prefetch_related('pdb_code__web_resource')

    mutations = MutationExperiment.objects.filter(
        protein__in=proteins).prefetch_related('residue__generic_number',
                                               'exp_qual', 'ligand')

    interactions = ResidueFragmentInteraction.objects.filter(
        structure_ligand_pair__structure__protein_conformation__protein__parent__in
        =proteins,
        structure_ligand_pair__annotated=True).exclude(
            interaction_type__type='hidden').order_by(
                'rotamer__residue__sequence_number')
    interaction_list = {}
    for interaction in interactions:
        if interaction.rotamer.residue.generic_number:
            gn = interaction.rotamer.residue.generic_number.label
            aa = interaction.rotamer.residue.amino_acid
            interactiontype = interaction.interaction_type.name
            if gn not in interaction_list:
                interaction_list[gn] = []
            interaction_list[gn].append([aa, interactiontype])

    mutations_list = {}
    for mutation in mutations:
        if not mutation.residue.generic_number:
            continue  #cant map those without display numbers
        if mutation.residue.generic_number.label not in mutations_list:
            mutations_list[mutation.residue.generic_number.label] = []
        if mutation.ligand:
            ligand = mutation.ligand.name
        else:
            ligand = ''
        if mutation.exp_qual:
            qual = mutation.exp_qual.qual
        else:
            qual = ''
        mutations_list[mutation.residue.generic_number.label].append(
            [mutation.foldchange,
             ligand.replace("'", "\\'"), qual])

    try:
        pc = ProteinConformation.objects.get(
            protein__family__slug=slug,
            protein__sequence_type__slug='consensus')
    except ProteinConformation.DoesNotExist:
        pc = ProteinConformation.objects.get(protein__family__slug=slug,
                                             protein__species_id=1,
                                             protein__sequence_type__slug='wt')

    residues = Residue.objects.filter(
        protein_conformation=pc).order_by('sequence_number').prefetch_related(
            'protein_segment', 'generic_number', 'display_generic_number')

    jsondata = {}
    jsondata_interaction = {}
    for r in residues:
        if r.generic_number:
            if r.generic_number.label in mutations_list:
                jsondata[r.sequence_number] = [
                    mutations_list[r.generic_number.label]
                ]
            if r.generic_number.label in interaction_list:
                jsondata_interaction[r.sequence_number] = interaction_list[
                    r.generic_number.label]

    HelixBox = DrawHelixBox(residues, 'Class A',
                            'family_diagram_preloaded_data')
    SnakePlot = DrawSnakePlot(
        residues, 'Class A',
        'family_diagram_preloaded_data')  ## was str(list_proteins)

    # process residues and return them in chunks of 10
    # this is done for easier scaling on smaller screens
    chunk_size = 10
    r_chunks = []
    r_buffer = []
    last_segment = False
    border = False
    title_cell_skip = 0
    for i, r in enumerate(residues):
        # title of segment to be written out for the first residue in each segment
        segment_title = False

        # keep track of last residues segment (for marking borders)
        if r.protein_segment.slug != last_segment:
            last_segment = r.protein_segment.slug
            border = True

        # if on a border, is there room to write out the title? If not, write title in next chunk
        if i == 0 or (border and len(last_segment) <=
                      (chunk_size - i % chunk_size)):
            segment_title = True
            border = False
            title_cell_skip += len(
                last_segment
            )  # skip cells following title (which has colspan > 1)

        if i and i % chunk_size == 0:
            r_chunks.append(r_buffer)
            r_buffer = []

        r_buffer.append((r, segment_title, title_cell_skip))

        # update cell skip counter
        if title_cell_skip > 0:
            title_cell_skip -= 1
    if r_buffer:
        r_chunks.append(r_buffer)

    context = {
        'pf': pf,
        'families': families,
        'structures': structures,
        'no_of_proteins': no_of_proteins,
        'no_of_human_proteins': no_of_human_proteins,
        'HelixBox': HelixBox,
        'SnakePlot': SnakePlot,
        'mutations': mutations,
        'r_chunks': r_chunks,
        'chunk_size': chunk_size,
        'mutations_pos_list': json.dumps(jsondata),
        'interaction_pos_list': json.dumps(jsondata_interaction)
    }

    return render(request, 'family/family_detail.html', context)