|
2 | 2 | import csv
|
3 | 3 | import json
|
4 | 4 | import sys
|
| 5 | +from collections import defaultdict |
5 | 6 | from django.views.decorators.csrf import csrf_exempt
|
6 | 7 | from django.conf import settings
|
7 | 8 | from django.contrib.auth.decorators import login_required
|
|
12 | 13 | from xbrowse_server.analysis.diagnostic_search import get_gene_diangostic_info
|
13 | 14 | from xbrowse_server.base.models import Project, Family, FamilySearchFlag, VariantNote, ProjectTag, VariantTag
|
14 | 15 | 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 |
15 | 17 | from xbrowse_server.api import utils as api_utils
|
16 | 18 | from xbrowse_server.api import forms as api_forms
|
17 | 19 | from xbrowse_server.mall import get_reference, get_datastore, get_mall
|
@@ -138,8 +140,9 @@ def cohort_variant_search(request):
|
138 | 140 | sys.stderr.write("cohort_variant_search - starting: %s %s\n" % (json.dumps(search_spec.toJSON()), cohort.xfamily().family_id))
|
139 | 141 | variants = api_utils.calculate_mendelian_variant_search(search_spec, cohort.xfamily())
|
140 | 142 |
|
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) |
143 | 146 |
|
144 | 147 | sys.stderr.write("cohort_variant_search - done save_results_for_spec: %s %s\n" % (json.dumps(search_spec.toJSON()), cohort.xfamily().family_id))
|
145 | 148 | api_utils.add_extra_info_to_variants_cohort(get_reference(), cohort, variants)
|
@@ -566,26 +569,108 @@ def combine_mendelian_families_spec(request):
|
566 | 569 |
|
567 | 570 | search_hash = request.GET.get('search_hash')
|
568 | 571 | 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) |
572 | 573 |
|
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 |
579 | 594 | 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 | + |
580 | 600 | 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) |
582 | 602 | 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) |
588 | 613 |
|
| 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 |
589 | 674 |
|
590 | 675 |
|
591 | 676 | @csrf_exempt
|
|
0 commit comments