Skip to content

Commit 42a4b1f

Browse files
committed
Merge pull request #166 from macarthur-lab/hotfix-download_variants_in_family_group_search
fix for issue #165 - downloading variants in family group search results
2 parents 9d91606 + 5ca7229 commit 42a4b1f

File tree

5 files changed

+128
-25
lines changed

5 files changed

+128
-25
lines changed

xbrowse_server/api/views.py

+102-17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import csv
33
import json
44
import sys
5+
from collections import defaultdict
56
from django.views.decorators.csrf import csrf_exempt
67
from django.conf import settings
78
from django.contrib.auth.decorators import login_required
@@ -12,6 +13,7 @@
1213
from xbrowse_server.analysis.diagnostic_search import get_gene_diangostic_info
1314
from xbrowse_server.base.models import Project, Family, FamilySearchFlag, VariantNote, ProjectTag, VariantTag
1415
from xbrowse_server.api.utils import get_project_and_family_for_user, get_project_and_cohort_for_user, add_extra_info_to_variants_family
16+
from xbrowse.variant_search.family import get_variants_with_inheritance_mode
1517
from xbrowse_server.api import utils as api_utils
1618
from xbrowse_server.api import forms as api_forms
1719
from xbrowse_server.mall import get_reference, get_datastore, get_mall
@@ -138,8 +140,9 @@ def cohort_variant_search(request):
138140
sys.stderr.write("cohort_variant_search - starting: %s %s\n" % (json.dumps(search_spec.toJSON()), cohort.xfamily().family_id))
139141
variants = api_utils.calculate_mendelian_variant_search(search_spec, cohort.xfamily())
140142

141-
sys.stderr.write("cohort_variant_search - done calculate_mendelian_variant_search: %s %s\n" % (json.dumps(search_spec.toJSON()), cohort.xfamily().family_id))
142-
search_hash = cache_utils.save_results_for_spec(project.project_id, search_spec.toJSON(), [v.toJSON() for v in variants])
143+
list_of_variants = [v.toJSON() for v in variants]
144+
sys.stderr.write("cohort_variant_search - done calculate_mendelian_variant_search: %s %s %s\n" % (json.dumps(search_spec.toJSON()), cohort.xfamily().family_id, len(list_of_variants)))
145+
search_hash = cache_utils.save_results_for_spec(project.project_id, search_spec.toJSON(), list_of_variants)
143146

144147
sys.stderr.write("cohort_variant_search - done save_results_for_spec: %s %s\n" % (json.dumps(search_spec.toJSON()), cohort.xfamily().family_id))
145148
api_utils.add_extra_info_to_variants_cohort(get_reference(), cohort, variants)
@@ -566,26 +569,108 @@ def combine_mendelian_families_spec(request):
566569

567570
search_hash = request.GET.get('search_hash')
568571
search_spec, genes = cache_utils.get_cached_results(project.project_id, search_hash)
569-
if genes is None:
570-
genes = api_utils.calculate_combine_mendelian_families(family_group, search_spec)
571-
api_utils.add_extra_info_to_genes(project, get_reference(), genes)
572+
search_spec_obj = MendelianVariantSearchSpec.fromJSON(search_spec)
572573

573-
if request.GET.get('return_type', '') != 'csv':
574-
return JSONResponse({
575-
'is_error': False,
576-
'genes': genes,
577-
'search_spec': search_spec,
578-
})
574+
if request.GET.get('return_type') != 'csv' or not request.GET.get('group_by_variants'):
575+
if genes is None:
576+
genes = api_utils.calculate_combine_mendelian_families(family_group, search_spec)
577+
api_utils.add_extra_info_to_genes(project, get_reference(), genes)
578+
579+
if request.GET.get('return_type') != 'csv':
580+
return JSONResponse({
581+
'is_error': False,
582+
'genes': genes,
583+
'search_spec': search_spec,
584+
})
585+
else:
586+
response = HttpResponse(content_type='text/csv')
587+
response['Content-Disposition'] = 'attachment; filename="family_group_results_{}.csv"'.format(search_hash)
588+
writer = csv.writer(response)
589+
writer.writerow(["gene", "# families", "family list", "chrom", "start", "end"])
590+
for gene in genes:
591+
family_id_list = [family_id for (project_id, family_id) in gene["family_id_list"]]
592+
writer.writerow(map(str, [gene["gene_name"], len(family_id_list), " ".join(family_id_list), gene["chr"], gene["start"], gene["end"], ""]))
593+
return response
579594
else:
595+
# download results grouped by variant
596+
indiv_id_list = []
597+
for family in family_group.get_families():
598+
indiv_id_list.extend(family.indiv_ids_with_variant_data())
599+
580600
response = HttpResponse(content_type='text/csv')
581-
response['Content-Disposition'] = 'attachment; filename="family_group_results_{}.csv"'.format(search_hash)
601+
response['Content-Disposition'] = 'attachment; filename="xbrowse_results_{}.csv"'.format(search_hash)
582602
writer = csv.writer(response)
583-
writer.writerow(["gene", "# families", "family list", "chrom", "start", "end"])
584-
for gene in genes:
585-
family_id_list = [family_id for (project_id, family_id) in gene["family_id_list"]]
586-
writer.writerow(map(str, [gene["gene_name"], len(family_id_list), " ".join(family_id_list), gene["chr"], gene["start"], gene["end"], ""]))
587-
return response
603+
604+
headers = ['genes','chr','pos','ref','alt','worst_annotation' ]
605+
headers.extend(project.get_reference_population_slugs())
606+
headers.extend([ 'polyphen','sift','muttaster','fathmm'])
607+
for indiv_id in indiv_id_list:
608+
headers.append(indiv_id)
609+
headers.append(indiv_id+'_gq')
610+
headers.append(indiv_id+'_dp')
611+
612+
writer.writerow(headers)
588613

614+
mall = get_mall(project.project_id)
615+
variant_key_to_individual_id_to_variant = defaultdict(dict)
616+
variant_key_to_variant = {}
617+
for family in family_group.get_families():
618+
for variant in get_variants_with_inheritance_mode(
619+
mall,
620+
family.xfamily(),
621+
search_spec_obj.inheritance_mode,
622+
search_spec_obj.variant_filter,
623+
search_spec_obj.quality_filter,
624+
):
625+
if len(variant.coding_gene_ids) == 0:
626+
continue
627+
628+
variant_key = (variant.xpos, variant.ref, variant.alt)
629+
variant_key_to_variant[variant_key] = variant
630+
for indiv_id in family.indiv_ids_with_variant_data():
631+
variant_key_to_individual_id_to_variant[variant_key][indiv_id] = variant
632+
633+
for variant_key in sorted(variant_key_to_individual_id_to_variant.keys()):
634+
variant = variant_key_to_variant[variant_key]
635+
individual_id_to_variant = variant_key_to_individual_id_to_variant[variant_key]
636+
637+
genes = [mall.reference.get_gene_symbol(gene_id) for gene_id in variant.coding_gene_ids]
638+
fields = []
639+
fields.append(','.join(genes))
640+
fields.extend([
641+
variant.chr,
642+
str(variant.pos),
643+
variant.ref,
644+
variant.alt,
645+
variant.annotation.get('vep_group', '.'),
646+
])
647+
for ref_population_slug in project.get_reference_population_slugs():
648+
fields.append(variant.annotation['freqs'][ref_population_slug])
649+
for field_key in ['polyphen', 'sift', 'muttaster', 'fathmm']:
650+
fields.append(variant.annotation[field_key])
651+
652+
for indiv_id in indiv_id_list:
653+
variant = individual_id_to_variant.get(indiv_id)
654+
genotype = None
655+
if variant is not None:
656+
genotype = variant.get_genotype(indiv_id)
657+
658+
if genotype is None:
659+
fields.extend(['.', '.', '.'])
660+
else:
661+
if genotype.num_alt == 0:
662+
fields.append("%s/%s" % (variant.ref, variant.ref))
663+
elif genotype.num_alt == 1:
664+
fields.append("%s/%s" % (variant.ref, variant.alt))
665+
elif genotype.num_alt == 2:
666+
fields.append("%s/%s" % (variant.alt, variant.alt))
667+
else:
668+
fields.append("./.")
669+
670+
fields.append(str(genotype.gq) if genotype.gq is not None else '.')
671+
fields.append(genotype.extras['dp'] if genotype.extras.get('dp') is not None else '.')
672+
writer.writerow(fields)
673+
return response
589674

590675

591676
@csrf_exempt

xbrowse_server/base/management/commands/add_project.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def handle(self, *args, **options):
99
if len(args)<1 or not args[0]:
1010
print '\n\n'
1111
print 'Creates a project in xBrowse.\n'
12-
print 'Please provide a project ID as an argument. '
12+
print 'Please provide a project ID as an argument. Optionally, provide a more human-readable project name as a second argument. '
1313
print 'Example: python manage.py add_project 1kg\n'
1414
sys.exit()
1515
project_id = args[0]
@@ -19,9 +19,15 @@ def handle(self, *args, **options):
1919
if Project.objects.filter(project_id=project_id).exists():
2020
print '\nSorry, I am unable to create that project since it exists already\n'
2121
sys.exit()
22-
print '\n\ncreating project',project_id,'in xBrowse.\n\n'
22+
23+
project_name = None
24+
if len(args) > 1:
25+
project_name = args[1]
26+
27+
print('Creating project %(project_id)s' % locals())
28+
2329
try:
24-
Project.objects.create(project_id=project_id)
30+
Project.objects.create(project_id=project_id, project_name=project_name)
2531
except Exception as e:
26-
print '\nError creating project in xBrowse:',e,'\n'
32+
print('\nError creating project:', e, '\n')
2733
sys.exit()

xbrowse_server/base/management/commands/batch_family_fileset_custom1.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def get_variants_for_inheritance_for_project(project, inheritance_mode):
3535

3636
# create search specification
3737
# this could theoretically differ by project, if there are different reference populations
38-
variant_filter = VariantFilter(so_annotations=SO_SEVERITY_ORDER) #get_default_variant_filter('moderate_impact')
38+
variant_filter = VariantFilter(so_annotations=SO_SEVERITY_ORDER, ref_freqs=[]) #get_default_variant_filter('moderate_impact')
3939
variant_filter.ref_freqs.append(('1kg_wgs_phase3', g1k_freq_threshold))
4040
variant_filter.ref_freqs.append(('1kg_wgs_phase3_popmax', g1k_popmax_freq_threshold))
4141
variant_filter.ref_freqs.append(('exac_v3', exac_freq_threshold))

xbrowse_server/staticfiles/js/family_group/combine_mendelian_families.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ var CombineMendelianFamiliesResultsView = Backbone.View.extend({
103103
"click a.gene-link": "gene_info",
104104
"click a.view-variants": "view_variants",
105105
'click .download-csv': 'download_csv',
106+
'click .download-csv-variants': 'download_csv_variants',
106107
},
107108

108109
gene_info: function(event) {
@@ -116,7 +117,11 @@ var CombineMendelianFamiliesResultsView = Backbone.View.extend({
116117
},
117118

118119
download_csv: function() {
119-
this.hbc.download_csv();
120+
this.hbc.download_csv(false);
121+
},
122+
123+
download_csv_variants: function() {
124+
this.hbc.download_csv(true);
120125
},
121126
});
122127

@@ -273,13 +278,18 @@ var CombineMendelianFamiliesHBC = HeadBallCoach.extend({
273278
});
274279
},
275280

276-
download_csv: function() {
281+
download_csv: function(group_by_variants) {
277282
var params = {
278283
project_id: this.family_group.project_id,
279284
family_group: this.family_group.slug,
280285
search_hash: this.search_hash,
281286
return_type: 'csv',
282287
};
288+
289+
if(group_by_variants) {
290+
params['group_by_variants'] = true;
291+
}
292+
283293
window.location.href = URL_PREFIX + 'api/combine-mendelian-families-spec?' + $.param(params);
284294
},
285295

xbrowse_server/templates/client_templates/family_group.html

+3-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ <h4>Family &raquo; <strong><%= o.family_name %></strong></h4>
7676

7777
<div id="summary-container">
7878
<div class="alert alert-info">
79-
<a class="download-csv" style="float:right">Download Results</a>
79+
<a class="download-csv-variants" style="float:right;margin-left:30px">Download Variants</a>
80+
<a class="download-csv" style="float:right">Download Genes</a>
81+
8082
Returned <strong><%= genes.length %></strong> genes
8183
</div>
8284
</div>

0 commit comments

Comments
 (0)