Example #1
0
def update_family_pedigree_image(request, family_guid):
    """Updates the specified field in the Family model.

    Args:
        family_guid (string): GUID of the family.
    """

    family = Family.objects.get(guid=family_guid)

    # check permission
    check_project_permissions(family.project, request.user, can_edit=True)

    if len(request.FILES) == 0:
        pedigree_image = None
    elif len(request.FILES) > 1:
        return create_json_response({},
                                    status=400,
                                    reason='Received {} files'.format(
                                        len(request.FILES)))
    else:
        pedigree_image = next(iter((request.FILES.values())))

    update_model_from_json(family, {'pedigree_image': pedigree_image},
                           request.user)

    return create_json_response(
        {family.guid: _get_json_for_family(family, request.user)})
Example #2
0
def update_variant_tags_handler(request, variant_guid):
    saved_variant = SavedVariant.objects.get(guid=variant_guid)
    check_permissions(saved_variant.project, request.user, CAN_EDIT)

    request_json = json.loads(request.body)
    updated_tags = request_json.get('tags', [])
    updated_functional_data = request_json.get('functionalData', [])

    # Update tags

    existing_tag_guids = [tag['tagGuid'] for tag in updated_tags if tag.get('tagGuid')]
    new_tags = [tag for tag in updated_tags if not tag.get('tagGuid')]

    for tag in saved_variant.varianttag_set.exclude(guid__in=existing_tag_guids):
        delete_seqr_model(tag)

    for tag in new_tags:
        variant_tag_type = VariantTagType.objects.get(
            Q(name=tag['name']),
            Q(project=saved_variant.project) | Q(project__isnull=True)
        )
        create_seqr_model(
            VariantTag,
            saved_variant=saved_variant,
            variant_tag_type=variant_tag_type,
            search_parameters=request_json.get('searchParameters'),
            created_by=request.user,
        )

    # Update functional data

    existing_functional_guids = [tag['tagGuid'] for tag in updated_functional_data if tag.get('tagGuid')]

    for tag in saved_variant.variantfunctionaldata_set.exclude(guid__in=existing_functional_guids):
        delete_seqr_model(tag)

    for tag in updated_functional_data:
        if tag.get('tagGuid'):
            tag_model = VariantFunctionalData.objects.get(
                guid=tag.get('tagGuid'),
                functional_data_tag=tag.get('name'),
                saved_variant=saved_variant
            )
            update_model_from_json(tag_model, tag, allow_unknown_keys=True)
        else:
            create_seqr_model(
                VariantFunctionalData,
                saved_variant=saved_variant,
                functional_data_tag=tag.get('name'),
                metadata=tag.get('metadata'),
                search_parameters=request_json.get('searchParameters'),
                created_by=request.user,
            )

    return create_json_response({
        variant_guid: {
            'tags': [get_json_for_variant_tag(tag) for tag in saved_variant.varianttag_set.all()],
            'functionalData': [get_json_for_variant_functional_data(tag) for tag in saved_variant.variantfunctionaldata_set.all()]
        }
    })
Example #3
0
def save_individuals_metadata_table_handler(request, project_guid,
                                            upload_file_id):
    """
    Handler for 'save' requests to apply HPO terms tables previously uploaded through receive_individuals_metadata_handler
    """
    project = get_project_and_check_permissions(project_guid, request.user)

    json_records, _ = load_uploaded_file(upload_file_id)

    individual_guids = [record[INDIVIDUAL_GUID_COL] for record in json_records]
    individuals_by_guid = {
        i.guid: i
        for i in Individual.objects.filter(family__project=project,
                                           guid__in=individual_guids)
    }

    for record in json_records:
        individual = individuals_by_guid[record[INDIVIDUAL_GUID_COL]]
        update_model_from_json(individual, {
            k: record[k]
            for k in INDIVIDUAL_METADATA_FIELDS.keys() if k in record
        },
                               user=request.user)

    return create_json_response({
        'individualsByGuid': {
            individual['individualGuid']: individual
            for individual in _get_json_for_individuals(
                list(individuals_by_guid.values()),
                user=request.user,
                add_hpo_details=True,
            )
        },
    })
Example #4
0
def update_family_assigned_analyst(request, family_guid):
    """Updates the specified field in the Family model.

    Args:
        family_guid (string): GUID of the family.
    """
    family = Family.objects.get(guid=family_guid)
    # assigned_analyst can be edited by anyone with access to the project
    check_project_permissions(family.project, request.user, can_edit=False)

    request_json = json.loads(request.body)
    assigned_analyst_username = request_json.get('assigned_analyst_username')

    if assigned_analyst_username:
        try:
            assigned_analyst = User.objects.get(
                username=assigned_analyst_username)
        except Exception:
            return create_json_response({},
                                        status=400,
                                        reason="specified user does not exist")
    else:
        assigned_analyst = None
    update_model_from_json(family, {'assigned_analyst': assigned_analyst},
                           request.user)

    return create_json_response(
        {family.guid: _get_json_for_family(family, request.user)})
Example #5
0
def _update_locus_list_items(locus_list, new_genes, existing_gene_ids, new_intervals, existing_interval_guids, request_json, user):
    # Update genes
    for locus_list_gene in locus_list.locuslistgene_set.exclude(gene_id__in=existing_gene_ids):
        delete_seqr_model(locus_list_gene)

    for gene_id in new_genes.keys():
        create_seqr_model(
            LocusListGene,
            locus_list=locus_list,
            gene_id=gene_id,
            created_by=user,
        )

    # Update intervals
    genome_version = request_json.get('intervalGenomeVersion') or GENOME_VERSION_GRCh37
    locus_list.locuslistinterval_set.exclude(guid__in=existing_interval_guids).delete()
    for existing_interval in locus_list.locuslistinterval_set.all():
        update_model_from_json(existing_interval, {'genomeVersion': genome_version})
    for interval in new_intervals:
        LocusListInterval.objects.create(
            locus_list=locus_list,
            chrom=interval['chrom'].lstrip('chr'),
            start=interval['start'],
            end=interval['end'],
            genome_version=genome_version,
        )
Example #6
0
def update_project_saved_variant_json(project, family_id=None, user=None):
    saved_variants = SavedVariant.objects.filter(
        family__project=project).select_related('family')
    if family_id:
        saved_variants = saved_variants.filter(family__family_id=family_id)

    if not saved_variants:
        return []

    families = set()
    variant_ids = set()
    saved_variants_map = {}
    for v in saved_variants:
        families.add(v.family)
        variant_ids.add(v.variant_id)
        saved_variants_map[(v.variant_id, v.family.guid)] = v

    variants_json = get_es_variants_for_variant_ids(sorted(
        families, key=lambda f: f.guid),
                                                    sorted(variant_ids),
                                                    user=user)

    updated_saved_variant_guids = []
    for var in variants_json:
        for family_guid in var['familyGuids']:
            saved_variant = saved_variants_map.get(
                (var['variantId'], family_guid))
            if saved_variant:
                update_model_from_json(saved_variant,
                                       {'saved_variant_json': var}, user)
                updated_saved_variant_guids.append(saved_variant.guid)

    return updated_saved_variant_guids
Example #7
0
def update_variant_main_transcript(request, variant_guid, transcript_id):
    saved_variant = SavedVariant.objects.get(guid=variant_guid)
    check_project_permissions(saved_variant.family.project, request.user, can_edit=True)

    update_model_from_json(saved_variant, {'selected_main_transcript_id': transcript_id}, request.user)

    return create_json_response({'savedVariantsByGuid': {variant_guid: {'selectedMainTranscriptId': transcript_id}}})
Example #8
0
def create_saved_search_handler(request):
    request_json = json.loads(request.body)
    name = request_json.pop('name', None)
    if not name:
        error = '"Name" is required'
        return create_json_response({'error': error}, status=400, reason=error)

    if (request_json.get('inheritance') or {}).get('filter', {}).get('genotype'):
        error = 'Saved searches cannot include custom genotype filters'
        return create_json_response({'error': error}, status=400, reason=error)

    try:
        saved_search, _ = get_or_create_model_from_json(
            VariantSearch, {'search': request_json, 'created_by': request.user}, {'name': name}, request.user)
    except MultipleObjectsReturned:
        # Can't create a unique constraint on JSON field, so its possible that a duplicate gets made by accident
        dup_searches = VariantSearch.objects.filter(
            search=request_json,
            created_by=request.user,
        ).order_by('created_date')
        saved_search = dup_searches.first()
        VariantSearch.bulk_delete(request.user, queryset=dup_searches.exclude(guid=saved_search.guid))
        update_model_from_json(saved_search, {'name': name}, request.user)
    except IntegrityError:
        error = 'Saved search with name "{}" already exists'.format(name)
        return create_json_response({'error': error}, status=400, reason=error)

    return create_json_response({
        'savedSearchesByGuid': {
            saved_search.guid: get_json_for_saved_search(saved_search, request.user)
        }
    })
Example #9
0
def update_locus_list_handler(request, locus_list_guid):
    locus_list = LocusList.objects.get(guid=locus_list_guid)
    check_user_created_object_permissions(locus_list,
                                          request.user,
                                          permission_level=CAN_EDIT)

    request_json = json.loads(request.body)

    genes_by_id, intervals, invalid_items = parse_locus_list_items(
        request_json)
    if invalid_items and not request_json.get('ignoreInvalidItems'):
        return create_json_response({'invalidLocusListItems': invalid_items},
                                    status=400,
                                    reason=INVALID_ITEMS_ERROR)

    update_model_from_json(locus_list, request_json, allow_unknown_keys=True)
    if genes_by_id is not None:
        _update_locus_list_items(locus_list, genes_by_id, intervals,
                                 request_json)

    return create_json_response({
        'locusListsByGuid': {
            locus_list.guid: get_json_for_locus_list(locus_list, request.user)
        },
        'genesById': genes_by_id or {},
    })
Example #10
0
def update_individual_hpo_terms(request, individual_guid):
    """Updates features fields for the given Individual
    """

    individual = Individual.objects.get(guid=individual_guid)

    project = individual.family.project

    check_project_permissions(project, request.user, can_edit=True)

    request_json = json.loads(request.body)

    update_json = {
        key:
        [get_parsed_feature(feature)
         for feature in request_json[key]] if request_json.get(key) else None
        for key in [
            'features', 'absentFeatures', 'nonstandardFeatures',
            'absentNonstandardFeatures'
        ]
    }
    update_model_from_json(individual, update_json, user=request.user)

    return create_json_response({
        individual.guid:
        _get_json_for_individual(individual,
                                 request.user,
                                 add_hpo_details=True)
    })
Example #11
0
def _update_tags(saved_variants,
                 tags_json,
                 user,
                 tag_key='tags',
                 model_cls=VariantTag,
                 get_tag_create_data=_get_tag_type_create_data):
    tags = tags_json.get(tag_key, [])
    updated_models = []
    for tag in tags:
        if tag.get('tagGuid'):
            model = model_cls.objects.get(guid=tag.get('tagGuid'))
            update_model_from_json(model,
                                   tag,
                                   user=user,
                                   allow_unknown_keys=True)
        else:
            create_data = get_tag_create_data(tag,
                                              saved_variants=saved_variants)
            create_data.update({
                'metadata': tag.get('metadata'),
                'search_hash': tags_json.get('searchHash'),
            })
            model = create_model_from_json(model_cls, create_data, user)
            model.saved_variants.set(saved_variants)

        updated_models.append(model)
    return updated_models
Example #12
0
def update_mme_submission(request, submission_guid=None):
    """
    Create or update the submission for the given individual.
    """
    submission_json = json.loads(request.body)
    phenotypes = submission_json.pop('phenotypes', [])
    gene_variants = submission_json.pop('geneVariants', [])
    if not phenotypes and not gene_variants:
        return create_json_response({}, status=400, reason='Genotypes or phentoypes are required')

    genomic_features = []
    for gene_variant in gene_variants:
        if not gene_variant.get('geneId'):
            return create_json_response({}, status=400, reason='Gene id is required for genomic features')
        feature = {'gene': {'id': gene_variant['geneId']}}
        if 'numAlt' in gene_variant and gene_variant['numAlt'] > 0:
            feature['zygosity'] = gene_variant['numAlt']
        if gene_variant.get('pos'):
            genome_version = gene_variant['genomeVersion']
            feature['variant'] = {
                'referenceName': gene_variant['chrom'],
                'start': gene_variant['pos'],
                'assembly': GENOME_VERSION_LOOKUP.get(genome_version, genome_version),
            }
            if gene_variant.get('alt'):
                feature['variant'].update({
                    'alternateBases': gene_variant['alt'],
                    'referenceBases': gene_variant['ref'],
                })
            elif gene_variant.get('end'):
                feature['variant']['end'] = gene_variant['end']
        genomic_features.append(feature)

    submission_json.update({
        'features': phenotypes,
        'genomicFeatures': genomic_features,
        'deletedDate': None,
        'deletedBy': None,
    })

    if submission_guid:
        submission = MatchmakerSubmission.objects.get(guid=submission_guid)
        check_mme_permissions(submission, request.user)
    else:
        individual_guid = submission_json.get('individualGuid')
        if not individual_guid:
            return create_json_response({}, status=400, reason='Individual is required for a new submission')
        individual = Individual.objects.get(guid=individual_guid)
        check_project_permissions(individual.family.project, request.user)
        submission = MatchmakerSubmission.objects.create(
            individual=individual,
            submission_id=individual.guid,
            label=individual.individual_id,
        )

    update_model_from_json(submission, submission_json, allow_unknown_keys=True)

    # search for new matches
    return _search_matches(submission, request.user)
Example #13
0
def update_variant_tags_handler(request, variant_guid):
    saved_variant = SavedVariant.objects.get(guid=variant_guid)
    check_permissions(saved_variant.family.project, request.user, CAN_VIEW)

    request_json = json.loads(request.body)
    updated_tags = request_json.get('tags', [])
    updated_functional_data = request_json.get('functionalData', [])

    # Update tags

    existing_tag_guids = [
        tag['tagGuid'] for tag in updated_tags if tag.get('tagGuid')
    ]

    saved_variant.varianttag_set.exclude(guid__in=existing_tag_guids).delete()

    _create_new_tags(saved_variant, request_json, request.user)

    # Update functional data

    existing_functional_guids = [
        tag['tagGuid'] for tag in updated_functional_data if tag.get('tagGuid')
    ]

    saved_variant.variantfunctionaldata_set.exclude(
        guid__in=existing_functional_guids).delete()

    for tag in updated_functional_data:
        if tag.get('tagGuid'):
            tag_model = VariantFunctionalData.objects.get(
                guid=tag.get('tagGuid'),
                functional_data_tag=tag.get('name'),
                saved_variant=saved_variant)
            update_model_from_json(tag_model, tag, allow_unknown_keys=True)
        else:
            VariantFunctionalData.objects.create(
                saved_variant=saved_variant,
                functional_data_tag=tag.get('name'),
                metadata=tag.get('metadata'),
                search_hash=request_json.get('searchHash'),
                created_by=request.user,
            )

    return create_json_response({
        'savedVariantsByGuid': {
            variant_guid: {
                'tags': [
                    get_json_for_variant_tag(tag)
                    for tag in saved_variant.varianttag_set.all()
                ],
                'functionalData': [
                    get_json_for_variant_functional_data(tag)
                    for tag in saved_variant.variantfunctionaldata_set.all()
                ]
            }
        }
    })
Example #14
0
def update_gene_note_handler(request, gene_id, note_guid):
    note = GeneNote.objects.get(guid=note_guid)
    check_user_created_object_permissions(note, request.user)

    request_json = json.loads(request.body)
    update_model_from_json(note, request_json, user=request.user, allow_unknown_keys=True)

    return create_json_response({'genesById': {gene_id: {
        'notes': _get_gene_notes(gene_id, request.user)
    }}})
Example #15
0
def update_variant_note_handler(request, variant_guid, note_guid):
    saved_variant = SavedVariant.objects.get(guid=variant_guid)
    check_permissions(saved_variant.project, request.user, CAN_EDIT)
    note = VariantNote.objects.get(guid=note_guid, saved_variant=saved_variant)

    request_json = json.loads(request.body)
    update_model_from_json(note, request_json, allow_unknown_keys=True)

    return create_json_response({variant_guid: {
        'notes': [get_json_for_variant_note(tag) for tag in saved_variant.variantnote_set.all()]
    }})
Example #16
0
def update_gene_note_handler(request, gene_id, note_guid):
    note = GeneNote.objects.get(guid=note_guid)
    if not _can_edit_note(note, request.user):
        raise PermissionDenied("User does not have permission to edit this note")

    request_json = json.loads(request.body)
    update_model_from_json(note, request_json, allow_unknown_keys=True)

    return create_json_response({'genesById': {gene_id: {
        'notes': _get_gene_notes(gene_id, request.user)
    }}})
Example #17
0
def update_variant_note_handler(request, variant_guid, note_guid):
    saved_variant = SavedVariant.objects.get(guid=variant_guid)
    check_permissions(saved_variant.project, request.user, CAN_VIEW)
    note = VariantNote.objects.get(guid=note_guid, saved_variant=saved_variant)

    request_json = json.loads(request.body)
    update_model_from_json(note, request_json, allow_unknown_keys=True)

    return create_json_response({'savedVariantsByGuid': {variant_guid: {
        'notes': [get_json_for_variant_note(tag) for tag in saved_variant.variantnote_set.all()]
    }}})
Example #18
0
def _update_samples(matched_sample_id_to_sample_record, elasticsearch_index=None, dataset_path=None, sample_dataset_path_mapping=None):
    loaded_date = timezone.now()
    for sample_id, sample in matched_sample_id_to_sample_record.items():
        sample_update_json = {
            'dataset_file_path': dataset_path or sample_dataset_path_mapping[sample_id],
        }
        if elasticsearch_index:
            sample_update_json['elasticsearch_index'] = elasticsearch_index
        if sample.sample_status != Sample.SAMPLE_STATUS_LOADED:
            sample_update_json['sample_status'] = Sample.SAMPLE_STATUS_LOADED
            sample_update_json['loaded_date'] = loaded_date
        update_model_from_json(sample, sample_update_json)
Example #19
0
def update_gene_note_handler(request, gene_id, note_guid):
    note = GeneNote.objects.get(guid=note_guid)
    if not _can_edit_note(note, request.user):
        raise PermissionDenied(
            "User does not have permission to edit this note")

    request_json = json.loads(request.body)
    update_model_from_json(note, request_json, allow_unknown_keys=True)

    return create_json_response(
        {gene_id: {
            'notes': _get_gene_notes(gene_id, request.user)
        }})
Example #20
0
def update_variant_note_handler(request, variant_guids, note_guid):
    note = VariantNote.objects.get(guid=note_guid)
    projects = {saved_variant.family.project for saved_variant in note.saved_variants.all()}
    for project in projects:
        check_project_permissions(project, request.user)
    request_json = json.loads(request.body)
    update_model_from_json(note, request_json, user=request.user, allow_unknown_keys=True)

    note_json = get_json_for_variant_note(note, add_variant_guids=False)
    note_json['variantGuids'] = variant_guids.split(',')

    return create_json_response({
        'variantNotesByGuid': {note.guid: note_json},
    })
Example #21
0
def update_variant_tags_handler(request, variant_guid):
    saved_variant = SavedVariant.objects.get(guid=variant_guid)
    check_permissions(saved_variant.project, request.user, CAN_VIEW)

    request_json = json.loads(request.body)
    updated_tags = request_json.get('tags', [])
    updated_functional_data = request_json.get('functionalData', [])

    # Update tags

    existing_tag_guids = [tag['tagGuid'] for tag in updated_tags if tag.get('tagGuid')]

    for tag in saved_variant.varianttag_set.exclude(guid__in=existing_tag_guids):
        delete_seqr_model(tag)

    _create_new_tags(saved_variant, request_json, request.user)

    # Update functional data

    existing_functional_guids = [tag['tagGuid'] for tag in updated_functional_data if tag.get('tagGuid')]

    for tag in saved_variant.variantfunctionaldata_set.exclude(guid__in=existing_functional_guids):
        delete_seqr_model(tag)

    for tag in updated_functional_data:
        if tag.get('tagGuid'):
            tag_model = VariantFunctionalData.objects.get(
                guid=tag.get('tagGuid'),
                functional_data_tag=tag.get('name'),
                saved_variant=saved_variant
            )
            update_model_from_json(tag_model, tag, allow_unknown_keys=True)
        else:
            create_seqr_model(
                VariantFunctionalData,
                saved_variant=saved_variant,
                functional_data_tag=tag.get('name'),
                metadata=tag.get('metadata'),
                search_hash=request_json.get('searchHash'),
                created_by=request.user,
            )

    return create_json_response({'savedVariantsByGuid': {
        variant_guid: {
            'tags': [get_json_for_variant_tag(tag) for tag in saved_variant.varianttag_set.all()],
            'functionalData': [get_json_for_variant_functional_data(tag) for tag in saved_variant.variantfunctionaldata_set.all()]
        }
    }})
Example #22
0
def update_analysis_group_handler(request, project_guid, analysis_group_guid=None):
    project = get_project_and_check_permissions(project_guid, request.user, permission_level=CAN_EDIT)

    request_json = json.loads(request.body)
    missing_fields = [field for field in REQUIRED_FIELDS.keys() if not request_json.get(field)]
    if missing_fields:
        return create_json_response(
            {}, status=400, reason='Missing required field(s): {missing_field_names}'.format(
                missing_field_names=', '.join([REQUIRED_FIELDS[field] for field in missing_fields])
            ))

    families = Family.objects.filter(guid__in=request_json['familyGuids']).only('guid')
    if len(families) != len(request_json['familyGuids']):
        return create_json_response(
            {}, status=400, reason='The following families do not exist: {missing_families}'.format(
                missing_families=', '.join(set(request_json['familyGuids']) - set([family.guid for family in families]))
            ))

    if analysis_group_guid:
        analysis_group = AnalysisGroup.objects.get(guid=analysis_group_guid, project=project)
        update_model_from_json(analysis_group, request_json, allow_unknown_keys=True)
    else:
        try:
            analysis_group = create_seqr_model(
                AnalysisGroup,
                project=project,
                name=request_json['name'],
                description=request_json.get('description'),
                created_by=request.user,
            )
        except IntegrityError:
            return create_json_response(
                {}, status=400, reason='An analysis group named "{name}" already exists for project "{project}"'.format(
                    name=request_json['name'], project=project.name
                ))

    analysis_group.families.set(families)
    base_family_group = find_matching_xbrowse_model(analysis_group)
    if base_family_group:
        base_family_group.families.set(BaseFamily.objects.filter(seqr_family__in=families))

    return create_json_response({
        'analysisGroupsByGuid': {
            analysis_group.guid: get_json_for_analysis_group(analysis_group, project_guid=project_guid)
        },
    })
Example #23
0
def _update_case_review(model,
                        project,
                        request,
                        field,
                        get_response_json,
                        additional_updates=None):
    if not has_case_review_permissions(project, request.user):
        raise PermissionDenied('User cannot edit case review for this project')

    update_json = {field: json.loads(request.body).get(field)}
    if additional_updates:
        update_json.update(additional_updates)

    update_model_from_json(model, update_json, user=request.user)

    return create_json_response(
        {model.guid: get_response_json(model, request.user)})
Example #24
0
def update_saved_search_handler(request, saved_search_guid):
    search = VariantSearch.objects.get(guid=saved_search_guid)
    if search.created_by != request.user:
        return create_json_response({}, status=403, reason='User does not have permission to edit this search')

    request_json = json.loads(request.body)
    name = request_json.pop('name', None)
    if not name:
        return create_json_response({}, status=400, reason='"Name" is required')

    update_model_from_json(search, {'name': name}, request.user)

    return create_json_response({
        'savedSearchesByGuid': {
            saved_search_guid: get_json_for_saved_search(search, request.user)
        }
    })
Example #25
0
def _update_existing_user(user, project, request_json):
    update_model_from_json(user, _get_user_json(request_json), user=user)

    project.can_view_group.user_set.add(user)
    if request_json.get('hasEditPermissions'):
        project.can_edit_group.user_set.add(user)
    else:
        project.can_edit_group.user_set.remove(user)

    return create_json_response({
        'projectsByGuid': {
            project.guid: {
                'collaborators':
                get_json_for_project_collaborator_list(user, project)
            }
        }
    })
Example #26
0
def update_mme_result_status(request, matchmaker_result_guid):
    """
    Looks for matches for the given individual. Expects a single patient (MME spec) in the POST
    data field under key "patient_data"
    Args:
        project_id,indiv_id and POST all data in POST under key "patient_data"
    Returns:
        Status code and results
    """
    result = MatchmakerResult.objects.get(guid=matchmaker_result_guid)
    check_mme_permissions(result.submission, request.user)

    request_json = json.loads(request.body)
    update_model_from_json(result, request_json, allow_unknown_keys=True)

    return create_json_response({
        'mmeResultsByGuid': {matchmaker_result_guid: {'matchStatus': _get_json_for_model(result)}},
    })
Example #27
0
def update_locus_list_handler(request, locus_list_guid):
    locus_list = LocusList.objects.get(guid=locus_list_guid)
    check_object_permissions(locus_list, request.user, permission_level=CAN_EDIT)

    request_json = json.loads(request.body)

    genes_by_id, intervals, invalid_items = parse_locus_list_items(request_json)
    if invalid_items and not request_json.get('ignoreInvalidItems'):
        return create_json_response({'invalidLocusListItems': invalid_items}, status=400, reason=INVALID_ITEMS_ERROR)

    update_model_from_json(locus_list, request_json, allow_unknown_keys=True)
    if genes_by_id is not None:
        _update_locus_list_items(locus_list, genes_by_id, intervals, request_json, request.user)

    return create_json_response({
        'locusListsByGuid': {locus_list.guid: get_json_for_locus_list(locus_list, request.user)},
        'genesById': genes_by_id or {},
    })
Example #28
0
def update_analysis_group_handler(request, project_guid, analysis_group_guid=None):
    project = get_project_and_check_permissions(project_guid, request.user, permission_level=CAN_EDIT)

    request_json = json.loads(request.body)
    missing_fields = [field for field in REQUIRED_FIELDS.keys() if not request_json.get(field)]
    if missing_fields:
        return create_json_response(
            {}, status=400, reason='Missing required field(s): {missing_field_names}'.format(
                missing_field_names=', '.join([REQUIRED_FIELDS[field] for field in missing_fields])
            ))

    families = Family.objects.filter(guid__in=request_json['familyGuids']).only('guid')
    if len(families) != len(request_json['familyGuids']):
        return create_json_response(
            {}, status=400, reason='The following families do not exist: {missing_families}'.format(
                missing_families=', '.join(set(request_json['familyGuids']) - set([family.guid for family in families]))
            ))

    if analysis_group_guid:
        analysis_group = AnalysisGroup.objects.get(guid=analysis_group_guid, project=project)
        update_model_from_json(analysis_group, request_json, allow_unknown_keys=True)
    else:
        try:
            analysis_group = create_seqr_model(
                AnalysisGroup,
                project=project,
                name=request_json['name'],
                description=request_json.get('description'),
                created_by=request.user,
            )
        except IntegrityError:
            return create_json_response(
                {}, status=400, reason='An analysis group named "{name}" already exists for project "{project}"'.format(
                    name=request_json['name'], project=project.name
                ))

    analysis_group.families.set(families)
    update_xbrowse_family_group_families(analysis_group, families)

    return create_json_response({
        'analysisGroupsByGuid': {
            analysis_group.guid: get_json_for_analysis_group(analysis_group, project_guid=project_guid)
        },
    })
Example #29
0
def send_mme_contact_email(request, matchmaker_result_guid):
    """
    Sends the given email and updates the contacted status for the match
    Args:
        matchmaker_result_guid
    Returns:
        Status code and results
    """
    result = MatchmakerResult.objects.get(guid=matchmaker_result_guid)
    project = result.individual.family.project
    check_permissions(project, request.user)

    request_json = json.loads(request.body)
    email_message = EmailMessage(
        subject=request_json['subject'],
        body=request_json['body'],
        to=map(lambda s: s.strip(), request_json['to'].split(',')),
        from_email='*****@*****.**',
    )
    try:
        email_message.send()
    except Exception as e:
        message = e.message
        json_body = {}
        if hasattr(e, 'response'):
            message = e.response.content
            try:
                json_body = e.response.json()
            except Exception:
                pass
        return create_json_response(json_body,
                                    status=getattr(e, 'status_code', 400),
                                    reason=message)

    update_model_from_json(result, {'weContacted': True})

    return create_json_response({
        'mmeResultsByGuid': {
            matchmaker_result_guid: {
                'matchStatus': _get_json_for_model(result)
            }
        },
    })
Example #30
0
def update_mme_result_status(request, matchmaker_result_guid):
    """
    Looks for matches for the given individual. Expects a single patient (MME spec) in the POST
    data field under key "patient_data"
    Args:
        project_id,indiv_id and POST all data in POST under key "patient_data"
    Returns:
        Status code and results
    """
    result = MatchmakerResult.objects.get(guid=matchmaker_result_guid)
    project = result.individual.family.project
    check_permissions(project, request.user)

    request_json = json.loads(request.body)
    update_model_from_json(result, request_json, allow_unknown_keys=True)

    return create_json_response({
        'mmeResultsByGuid': {matchmaker_result_guid: {'matchStatus': _get_json_for_model(result)}},
    })
Example #31
0
def update_variant_functional_data_handler(request, variant_guids):
    request_json = json.loads(request.body)

    family_guid = request_json.pop('familyGuid')
    family = Family.objects.get(guid=family_guid)
    check_permissions(family.project, request.user, CAN_VIEW)

    all_variant_guids = set(variant_guids.split(','))
    saved_variants = SavedVariant.objects.filter(guid__in=all_variant_guids)
    if len(saved_variants) != len(all_variant_guids):
        error = 'Unable to find the following variant(s): {}'.format(
            ', '.join([guid for guid in all_variant_guids if guid not in {sv.guid for sv in saved_variants}]))
        return create_json_response({'error': error}, status=400, reason=error)

    updated_functional_data = request_json.get('functionalData', [])
    deleted_functional_guids = _delete_removed_tags(
        saved_variants, all_variant_guids, updated_functional_data, tag_type='functionaldata')

    updated_functional_models = []
    for tag in updated_functional_data:
        if tag.get('tagGuid'):
            functional_data = VariantFunctionalData.objects.get(guid=tag.get('tagGuid'))
            update_model_from_json(functional_data, tag, allow_unknown_keys=True)
        else:
            functional_data = VariantFunctionalData.objects.create(
                functional_data_tag=tag.get('name'),
                metadata=tag.get('metadata'),
                search_hash=request_json.get('searchHash'),
                created_by=request.user,
            )
            functional_data.saved_variants.set(saved_variants)
        updated_functional_models.append(functional_data)

    functional_updates = {tag['tagGuid']: tag for tag in get_json_for_variant_functional_data_tags(updated_functional_models)}
    functional_updates.update({guid: None for guid in deleted_functional_guids})

    return create_json_response({
        'savedVariantsByGuid': {saved_variant.guid: {
            'functionalDataGuids': [t.guid for t in saved_variant.variantfunctionaldata_set.all()],
        } for saved_variant in saved_variants},
        'variantFunctionalDataByGuid': functional_updates,
    })
Example #32
0
def delete_mme_submission(request, submission_guid):
    """
    Create or update the submission for the given individual.
    """
    submission = MatchmakerSubmission.objects.get(guid=submission_guid)
    check_mme_permissions(submission, request.user)

    if submission.deleted_date:
        return create_json_response(
            {}, status=402,
            reason='Matchmaker submission has already been deleted for {}'.format(submission.individual.individual_id),
        )

    deleted_date = datetime.now()
    update_model_from_json(submission, {'deleted_date': deleted_date, 'deleted_by': request.user}, request.user)

    for saved_result in MatchmakerResult.objects.filter(submission=submission):
        if not (saved_result.we_contacted or saved_result.host_contacted or saved_result.comments):
            saved_result.delete_model(request.user, user_can_delete=True)

    return create_json_response({'mmeSubmissionsByGuid': {submission.guid: {'deletedDate': deleted_date}}})
Example #33
0
def set_password(request, username):
    user = User.objects.get(username=username)

    request_json = json.loads(request.body)
    if not request_json.get('password'):
        return create_json_response({},
                                    status=400,
                                    reason='Password is required')

    user.set_password(request_json['password'])
    update_model_from_json(user,
                           _get_user_json(request_json),
                           user=user,
                           updated_fields={'password'})
    logger.info('Set password for user {}'.format(user.email),
                extra={'user': user})

    u = authenticate(username=username, password=request_json['password'])
    login(request, u)

    return create_json_response({'success': True})
Example #34
0
def save_hpo_table_handler(request, project_guid, upload_file_id):
    """
    Handler for 'save' requests to apply HPO terms tables previously uploaded through receive_hpo_table_handler
    """
    project = get_project_and_check_permissions(project_guid, request.user)

    json_records, _ = load_uploaded_file(upload_file_id)

    individual_guids = [
        record[INDIVIDUAL_GUID_COLUMN] for record in json_records
    ]
    individuals_by_guid = {
        i.guid: i
        for i in Individual.objects.filter(family__project=project,
                                           guid__in=individual_guids)
    }

    for record in json_records:
        individual = individuals_by_guid[record[INDIVIDUAL_GUID_COLUMN]]
        update_model_from_json(individual, {
            'features': [{
                'id': feature
            } for feature in record[HPO_TERMS_PRESENT_COLUMN]],
            'absent_features': [{
                'id': feature
            } for feature in record[HPO_TERMS_ABSENT_COLUMN]],
        },
                               user=request.user)

    return create_json_response({
        'individualsByGuid': {
            individual['individualGuid']: individual
            for individual in _get_json_for_individuals(
                list(individuals_by_guid.values()),
                user=request.user,
                add_hpo_details=True,
            )
        },
    })
Example #35
0
def send_mme_contact_email(request, matchmaker_result_guid):
    """
    Sends the given email and updates the contacted status for the match
    Args:
        matchmaker_result_guid
    Returns:
        Status code and results
    """
    result = MatchmakerResult.objects.get(guid=matchmaker_result_guid)
    check_mme_permissions(result.submission, request.user)

    request_json = json.loads(request.body)
    email_message = EmailMessage(
        subject=request_json['subject'],
        body=request_json['body'],
        to=[s.strip() for s in request_json['to'].split(',')],
        from_email=MME_DEFAULT_CONTACT_EMAIL,
    )
    try:
        email_message.send()
    except Exception as e:
        message = str(e)
        json_body = {}
        if hasattr(e, 'response'):
            message = e.response.content
            try:
                json_body = e.response.json()
            except Exception:
                json_body = {'message':message}
        return create_json_response(json_body, status=getattr(e, 'status_code', 400), reason=message)

    update_model_from_json(result, {'weContacted': True})

    return create_json_response({
        'mmeResultsByGuid': {matchmaker_result_guid: {'matchStatus': _get_json_for_model(result)}},
    })
    def handle(self, *args, **options):
        """transfer project"""
        project_arg = options['project']
        elasticsearch_index = options['es_index']

        project = Project.objects.get(
            Q(name=project_arg) | Q(guid=project_arg))
        logger.info('Updating project genome version for {}'.format(
            project.name))

        # Validate the provided index
        logger.info('Validating es index {}'.format(elasticsearch_index))
        sample_ids, index_metadata = get_elasticsearch_index_samples(
            elasticsearch_index)
        validate_index_metadata(index_metadata,
                                project,
                                elasticsearch_index,
                                genome_version=GENOME_VERSION_GRCh38)
        sample_type = index_metadata['sampleType']
        dataset_path = index_metadata['sourceFilePath']

        matched_sample_id_to_sample_record = match_sample_ids_to_sample_records(
            project=project,
            sample_ids=sample_ids,
            sample_type=sample_type,
            dataset_type=Sample.DATASET_TYPE_VARIANT_CALLS,
            elasticsearch_index=elasticsearch_index,
            sample_id_to_individual_id_mapping={},
        )

        unmatched_samples = set(sample_ids) - set(
            matched_sample_id_to_sample_record.keys())
        if len(unmatched_samples) > 0:
            raise CommandError(
                'Matches not found for ES sample ids: {}.'.format(
                    ', '.join(unmatched_samples)))

        prefetch_related_objects(matched_sample_id_to_sample_record.values(),
                                 'individual__family')
        included_families = {
            sample.individual.family
            for sample in matched_sample_id_to_sample_record.values()
        }
        missing_individuals = Individual.objects.filter(
            family__in=included_families,
            sample__is_active=True,
            sample__dataset_type=Sample.DATASET_TYPE_VARIANT_CALLS,
        ).exclude(sample__in=matched_sample_id_to_sample_record.values()
                  ).select_related('family')
        missing_family_individuals = defaultdict(list)
        for individual in missing_individuals:
            missing_family_individuals[individual.family].append(individual)

        if missing_family_individuals:
            raise CommandError(
                'The following families are included in the callset but are missing some family members: {}.'
                .format(', '.join([
                    '{} ({})'.format(
                        family.family_id,
                        ', '.join([i.individual_id for i in missing_indivs]))
                    for family, missing_indivs in
                    missing_family_individuals.items()
                ])))

        # Get and clean up expected saved variants
        saved_variant_models_by_guid = {
            v.guid: v
            for v in SavedVariant.objects.filter(family__project=project)
        }
        deleted_no_tags = set()
        for guid, variant in saved_variant_models_by_guid.items():
            if not (variant.varianttag_set.count()
                    or variant.variantnote_set.count()):
                deleted_no_tags.add(guid)

        if deleted_no_tags:
            if raw_input(
                    'Do you want to delete the following {} saved variants with no tags (y/n)?: {} '
                    .format(len(deleted_no_tags),
                            ', '.join(deleted_no_tags))) == 'y':
                for guid in deleted_no_tags:
                    saved_variant_models_by_guid.pop(guid).delete()
                logger.info('Deleted {} variants'.format(len(deleted_no_tags)))

        expected_families = {
            sv.family
            for sv in saved_variant_models_by_guid.values()
        }
        missing_families = expected_families - included_families
        if missing_families:
            raise CommandError(
                'The following families have saved variants but are missing from the callset: {}.'
                .format(', '.join([f.family_id for f in missing_families])))

        # Lift-over saved variants
        _update_variant_samples(matched_sample_id_to_sample_record,
                                elasticsearch_index, dataset_path)
        saved_variants = get_json_for_saved_variants(
            saved_variant_models_by_guid.values(), add_details=True)
        saved_variants_to_lift = [
            v for v in saved_variants
            if v['genomeVersion'] != GENOME_VERSION_GRCh38
        ]

        num_already_lifted = len(saved_variants) - len(saved_variants_to_lift)
        if num_already_lifted:
            if raw_input(
                    'Found {} saved variants already on Hg38. Continue with liftover (y/n)? '
                    .format(num_already_lifted)) != 'y':
                raise CommandError(
                    'Error: found {} saved variants already on Hg38'.format(
                        num_already_lifted))
        logger.info(
            'Lifting over {} variants (skipping {} that are already lifted)'.
            format(len(saved_variants_to_lift), num_already_lifted))

        liftover_to_38 = LiftOver('hg19', 'hg38')
        hg37_to_hg38_xpos = {}
        lift_failed = {}
        for v in saved_variants_to_lift:
            if not (hg37_to_hg38_xpos.get(v['xpos'])
                    or v['xpos'] in lift_failed):
                hg38_coord = liftover_to_38.convert_coordinate(
                    'chr{}'.format(v['chrom'].lstrip('chr')), int(v['pos']))
                if hg38_coord and hg38_coord[0]:
                    hg37_to_hg38_xpos[v['xpos']] = get_xpos(
                        hg38_coord[0][0], hg38_coord[0][1])
                else:
                    lift_failed[v['xpos']] = v

        if lift_failed:
            if raw_input(
                    'Unable to lift over the following {} coordinates. Continue with update (y/n)?: {} '
                    .format(
                        len(lift_failed), ', '.join([
                            '{}:{}-{}-{} ({})'.format(
                                v['chrom'], v['pos'], v['ref'], v['alt'],
                                ', '.join(v['familyGuids']))
                            for v in lift_failed.values()
                        ]))) != 'y':
                raise CommandError(
                    'Error: unable to lift over {} variants'.format(
                        len(lift_failed)))

        saved_variants_map = defaultdict(list)
        for v in saved_variants_to_lift:
            if hg37_to_hg38_xpos.get(v['xpos']):
                variant_model = saved_variant_models_by_guid[v['variantGuid']]
                saved_variants_map[(hg37_to_hg38_xpos[v['xpos']], v['ref'],
                                    v['alt'])].append(variant_model)

        es_variants = get_es_variants_for_variant_tuples(
            expected_families, saved_variants_map.keys())

        missing_variants = set(
            saved_variants_map.keys()) - {(v['xpos'], v['ref'], v['alt'])
                                          for v in es_variants}
        if missing_variants:
            missing_variant_strings = []
            for xpos, ref, alt in missing_variants:
                var_id = '{}-{}-{}'.format(xpos, ref, alt)
                for v in saved_variants_map[(xpos, ref, alt)]:
                    tags = v.varianttag_set.all()
                    notes = v.variantnote_set.all()
                    missing_variant_strings.append(
                        '{var_id} {family_id}: {tags} ({guid})'.format(
                            var_id=var_id,
                            family_id=v.family.family_id,
                            guid=v.guid,
                            tags=', '.join([
                                tag.variant_tag_type.name for tag in tags
                            ]) if tags else 'No Tags; {}'.format('; '.join(
                                [note.note for note in notes]))))
            if raw_input(
                    'Unable to find the following {} variants in the index. Continue with update (y/n)?:\n{}\n'
                    .format(len(missing_variants),
                            '\n'.join(missing_variant_strings))) != 'y':
                raise CommandError(
                    'Error: unable to find {} lifted-over variants'.format(
                        len(missing_variants)))

        logger.info('Successfully lifted over {} variants'.format(
            len(es_variants)))

        #  Update saved variants
        missing_family_count = 0
        for var in es_variants:
            saved_variant_models = saved_variants_map[(var['xpos'], var['ref'],
                                                       var['alt'])]
            missing_saved_variants = [
                v for v in saved_variant_models
                if v.family.guid not in var['familyGuids']
            ]
            if missing_saved_variants:
                variant_id = '{}-{}-{}-{}'.format(var['chrom'], var['pos'],
                                                  var['ref'], var['alt'])
                if raw_input(
                    ('Variant {} (hg37: {}) not find for expected families {}. Continue with update (y/n)? '
                     .format(
                         variant_id, missing_saved_variants[0].xpos,
                         ', '.join([
                             '{} ({})'.format(v.family.guid, v.guid)
                             for v in missing_saved_variants
                         ])))) == 'y':
                    var = get_single_es_variant(
                        [v.family for v in saved_variant_models],
                        variant_id,
                        return_all_queried_families=True)
                    missing_family_count += len(missing_saved_variants)
                else:
                    raise CommandError(
                        'Error: unable to find family data for lifted over variant'
                    )
            for saved_variant in saved_variant_models:
                saved_variant.xpos_start = var['xpos']
                saved_variant.saved_variant_json = var
                saved_variant.save()

        logger.info('Successfully updated {} variants'.format(
            len(es_variants)))

        # Update project and sample data
        update_model_from_json(project,
                               {'genome_version': GENOME_VERSION_GRCh38})

        reset_cached_search_results(project)

        logger.info('---Done---')
        logger.info(
            'Succesfully lifted over {} variants. Skipped {} failed variants. Family data not updated for {} variants'
            .format(len(es_variants),
                    len(missing_variants) + len(lift_failed),
                    missing_family_count))