Example #1
0
def phenotips_edit_handler(request, project_guid, patient_id):
    """Request the PhenoTips Edit page for the given patient_id, and forwards PhenoTips' response to the client.

    Args:
        request: Django HTTP request object
        project_guid (string): project GUID for the seqr project containing this individual
        patient_id (string): PhenoTips internal patient id
    """

    # query string forwarding needed for PedigreeEditor button
    query_string = request.META["QUERY_STRING"]
    url = "/bin/edit/data/{patient_id}?{query_string}".format(
        patient_id=patient_id, query_string=query_string)

    project = Project.objects.get(guid=project_guid)

    check_permissions(project, request.user, CAN_EDIT)

    auth_tuple = _get_phenotips_username_and_password(
        request.user, project, permissions_level=CAN_EDIT)

    return proxy_request(request,
                         url,
                         headers={},
                         auth_tuple=auth_tuple,
                         host=settings.PHENOTIPS_SERVER)
Example #2
0
def _phenotips_view_handler(request,
                            project_guid,
                            individual_guid,
                            url_template,
                            permission_level=CAN_VIEW):
    """Requests the PhenoTips PDF for the given patient_id, and forwards PhenoTips' response to the client.

    Args:
        request: Django HTTP request object
        project_guid (string): project GUID for the seqr project containing this individual
        individual_guid (string): individual GUID for the seqr individual corresponding to the desired patient
    """

    project = Project.objects.get(guid=project_guid)
    check_permissions(project, request.user, CAN_VIEW)

    individual = Individual.objects.get(guid=individual_guid)
    _create_patient_if_missing(project, individual)
    _set_phenotips_patient_id_if_missing(project, individual)

    # query string forwarding needed for PedigreeEditor button
    query_string = request.META["QUERY_STRING"]
    url = url_template.format(patient_id=individual.phenotips_patient_id,
                              query_string=query_string)

    auth_tuple = _get_phenotips_username_and_password(
        request.user, project, permissions_level=permission_level)

    return proxy_request(request,
                         url,
                         headers={},
                         auth_tuple=auth_tuple,
                         host=settings.PHENOTIPS_SERVER)
Example #3
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_permissions(family.project, request.user, CAN_EDIT)

    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 = request.FILES.values()[0]

    update_seqr_model(family, pedigree_image=pedigree_image)

    return create_json_response(
        {family.guid: _get_json_for_family(family, request.user)})
Example #4
0
def delete_mme_submission(request, individual_guid):
    """
    Create or update the submission for the given individual.
    """
    individual = Individual.objects.get(guid=individual_guid)
    project = individual.family.project
    check_permissions(project, request.user)

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

    matchbox_id = individual.mme_submitted_data['patient']['id']
    response = requests.delete(url=MME_DELETE_INDIVIDUAL_URL, headers=MME_HEADERS, data=json.dumps({'id': matchbox_id}))

    if response.status_code != 200:
        try:
            response_json = response.json()
        except Exception:
            response_json = {}
        return create_json_response(response_json, status=response.status_code, reason=response.content)

    deleted_date = datetime.now()
    individual.mme_deleted_date = deleted_date
    individual.mme_deleted_by = request.user
    individual.save()

    return create_json_response({'individualsByGuid': {individual_guid: {'mmeDeletedDate': deleted_date}}})
Example #5
0
def create_saved_variant_handler(request):
    variant_json = json.loads(request.body)
    family_guid = variant_json.pop('familyGuid')
    non_variant_json = {
        k: variant_json.pop(k, None) for k in ['searchHash', 'tags', 'functionalData', 'notes', 'note', 'submitToClinvar']
    }

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

    xpos = variant_json['xpos']
    ref = variant_json['ref']
    alt = variant_json['alt']
    # TODO remove project field from saved variants
    saved_variant = SavedVariant.objects.create(
        xpos=xpos,
        xpos_start=xpos,
        xpos_end=xpos + len(ref) - 1,
        ref=ref,
        alt=alt,
        family=family,
        project=family.project,
        saved_variant_json=json.dumps(variant_json)
    )

    if non_variant_json.get('note'):
        _create_variant_note(saved_variant, non_variant_json, request.user)
    elif non_variant_json.get('tags'):
        _create_new_tags(saved_variant, non_variant_json, request.user)

    variant_json.update(get_json_for_saved_variant(saved_variant, add_tags=True, project_guid=family.project.guid))
    return create_json_response({
        'savedVariantsByGuid': {saved_variant.guid: variant_json},
    })
Example #6
0
def delete_mme_submission(request, individual_guid):
    """
    Create or update the submission for the given individual.
    """
    individual = Individual.objects.get(guid=individual_guid)
    project = individual.family.project
    check_permissions(project, request.user)

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

    matchbox_id = individual.mme_submitted_data['patient']['id']
    response = requests.delete(url=MME_DELETE_INDIVIDUAL_URL, headers=MME_HEADERS, data=json.dumps({'id': matchbox_id}))

    if response.status_code != 200:
        try:
            response_json = response.json()
        except Exception:
            response_json = {}
        return create_json_response(response_json, status=response.status_code, reason=response.content)

    deleted_date = datetime.now()
    individual.mme_deleted_date = deleted_date
    individual.mme_deleted_by = request.user
    individual.save()

    for saved_result in MatchmakerResult.objects.filter(individual=individual):
        if not (saved_result.we_contacted or saved_result.host_contacted or saved_result.comments):
            saved_result.delete()

    return create_json_response({'individualsByGuid': {individual_guid: {'mmeDeletedDate': deleted_date}}})
Example #7
0
def get_individual_mme_matches(request, individual_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
    """
    individual = Individual.objects.get(guid=individual_guid)
    project = individual.family.project
    check_permissions(project, request.user)

    results = MatchmakerResult.objects.filter(individual=individual)

    saved_variants = get_json_for_saved_variants(
        SavedVariant.objects.filter(family=individual.family), add_tags=True, add_details=True,
        project=project, user=request.user)

    gene_ids = set()
    for variant in saved_variants:
        gene_ids.update(variant['transcripts'].keys())

    return _parse_mme_results(
        individual, results, request.user, additional_genes=gene_ids, response_json={
            'savedVariantsByGuid': {variant['variantGuid']: variant for variant in saved_variants}})
Example #8
0
def update_individual_handler(request, individual_guid):
    """Updates a single field in an Individual record.

    Args:
        request (object): Django HTTP Request object.
        individual_guid (string): GUID of the Individual.

    Request:
        body should be a json dictionary like: { 'value': xxx }

    Response:
        json dictionary representing the updated individual like:
            {
                <individualGuid> : {
                    individualId: xxx,
                    sex: xxx,
                    affected: xxx,
                    ...
                }
            }
    """

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

    project = individual.family.project

    check_permissions(project, request.user, CAN_EDIT)

    request_json = json.loads(request.body)

    update_individual_from_json(individual, request_json, user=request.user, allow_unknown_keys=True)

    return create_json_response({
        individual.guid: _get_json_for_individual(individual, request.user)
    })
Example #9
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)
    check_permissions(family.project, request.user, CAN_EDIT)

    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_seqr_model(family, assigned_analyst=assigned_analyst)

    return create_json_response(
        {family.guid: _get_json_for_family(family, request.user)})
Example #10
0
def update_individual_hpo_terms(request, individual_guid):
    individual = Individual.objects.get(guid=individual_guid)

    project = individual.family.project

    check_permissions(project, request.user, CAN_EDIT)

    features = json.loads(request.body)

    _create_patient_if_missing(project, individual)

    patient_json = _get_patient_data(project, individual)
    patient_json["features"] = features
    patient_json_string = json.dumps(patient_json)

    url = _phenotips_patient_url(individual)
    auth_tuple = _get_phenotips_uname_and_pwd_for_project(project.phenotips_user_id, read_only=False)
    _make_api_call('PUT', url, data=patient_json_string, auth_tuple=auth_tuple, expected_status_code=204)

    phenotips_patient_id = patient_json['id']
    phenotips_eid = patient_json.get('external_id')
    update_seqr_model(
        individual,
        phenotips_data=json.dumps(patient_json),
        phenotips_patient_id=phenotips_patient_id,
        phenotips_eid=phenotips_eid)

    return create_json_response({
        individual.guid: {
            'phenotipsData': patient_json,
            'phenotipsPatientId': phenotips_patient_id,
            'phenotipsEid': phenotips_eid
        }
    })
Example #11
0
def update_family_field_handler(request, family_guid, field_name):
    """Updates the specified field in the Family model.

    Args:
        family_guid (string): GUID of the family.
        field_name (string): Family model field name to update
    """

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

    # check permission
    project = family.project

    check_permissions(project, request.user, CAN_EDIT)

    request_json = json.loads(request.body)
    if "value" not in request_json:
        raise ValueError("Request is missing 'value' key: %s" %
                         (request.body, ))

    value = request_json['value']
    family_json = {field_name: value}
    update_family_from_json(family, family_json)

    _deprecated_update_original_family_field(project, family, field_name,
                                             value)

    return create_json_response(
        {family.guid: _get_json_for_family(family, request.user)})
Example #12
0
def update_variant_tags_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)

    deleted_tag_guids = _delete_removed_tags(saved_variants, all_variant_guids, request_json.get('tags', []))
    created_tags = _create_new_tags(saved_variants, request_json, request.user)
    tag_updates = {tag['tagGuid']: tag for tag in get_json_for_variant_tags(created_tags)}
    tag_updates.update({guid: None for guid in deleted_tag_guids})

    return create_json_response({
        'savedVariantsByGuid': {saved_variant.guid: {
            'tagGuids': [t.guid for t in saved_variant.varianttag_set.all()],
        } for saved_variant in saved_variants},
        'variantTagsByGuid': tag_updates,
    })
Example #13
0
def create_saved_variant_handler(request):
    variant_json = json.loads(request.body)
    family_guid = variant_json['familyGuid']

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

    if isinstance(variant_json['variant'], list):
        # are compound hets
        saved_variants = []
        for single_variant_json in variant_json['variant']:
            saved_variant, created = SavedVariant.objects.get_or_create(
                **_get_parsed_variant_args(single_variant_json, family))
            if created:
                saved_variant.saved_variant_json = single_variant_json
                saved_variant.save()
            saved_variants.append(saved_variant)
    else:
        saved_variant = SavedVariant.objects.create(
            saved_variant_json=variant_json['variant'],
            **_get_parsed_variant_args(variant_json['variant'], family))
        saved_variants = [saved_variant]

    if variant_json.get('note'):
        _create_variant_note(saved_variants, variant_json, request.user)
    elif variant_json.get('tags'):
        _create_new_tags(saved_variants, variant_json, request.user)

    return create_json_response(
        get_json_for_saved_variants_with_tags(saved_variants,
                                              add_details=True))
Example #14
0
def delete_variant_note_handler(request, variant_guids, note_guid):
    variant_guids = variant_guids.split(',')
    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_permissions(project, request.user, CAN_VIEW)
    note.delete()

    saved_variants_by_guid = {}
    for saved_variant in SavedVariant.objects.filter(guid__in=variant_guids):
        notes = saved_variant.variantnote_set.all()
        saved_variants_by_guid[saved_variant.guid] = {
            'noteGuids': [n.guid for n in notes]
        }
        if not notes:
            if not saved_variant.varianttag_set.count() > 0:
                saved_variant.delete()
                saved_variants_by_guid[saved_variant.guid] = None

    return create_json_response({
        'savedVariantsByGuid': saved_variants_by_guid,
        'variantNotesByGuid': {
            note_guid: None
        },
    })
Example #15
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 #16
0
def phenotips_edit_handler(request, project_guid, patient_id):
    """Request the PhenoTips Edit page for the given patient_id, and forwards PhenoTips' response to the client.

    Args:
        request: Django HTTP request object
        project_guid (string): project GUID for the seqr project containing this individual
        patient_id (string): PhenoTips internal patient id
    """

    # query string forwarding needed for PedigreeEditor button
    query_string = request.META["QUERY_STRING"]
    url = "/bin/edit/data/%(patient_id)s?%(query_string)s" % locals()

    project = Project.objects.get(guid=project_guid)

    check_permissions(project, request.user, CAN_EDIT)

    auth_tuple = _get_phenotips_username_and_password(request.user, project, permissions_level=CAN_EDIT)

    #if 'current_phenotips_session' not in request.session:
    #    phenotips_session = requests.Session()
    #    request.session['current_phenotips_session'] = pickle.dumps(phenotips_session)
    #else:
    #    phenotips_session = pickle.loads(request.session['current_phenotips_session'])

    return _send_request_to_phenotips('GET', url, scheme=request.scheme, auth_tuple=auth_tuple) #, session=phenotips_session)
Example #17
0
def update_individual_hpo_terms(request, individual_guid):
    individual = Individual.objects.get(guid=individual_guid)

    project = individual.family.project

    check_permissions(project, request.user, CAN_EDIT)

    features = json.loads(request.body)

    _create_patient_if_missing(project, individual)

    patient_json = _get_patient_data(project, individual)
    patient_json["features"] = features
    patient_json_string = json.dumps(patient_json)

    url = phenotips_patient_url(individual)
    auth_tuple = get_phenotips_uname_and_pwd_for_project(project.phenotips_user_id, read_only=False)
    make_phenotips_api_call('PUT', url, data=patient_json_string, auth_tuple=auth_tuple, expected_status_code=204)

    phenotips_patient_id = patient_json['id']
    phenotips_eid = patient_json.get('external_id')

    individual.phenotips_data = json.dumps(patient_json)
    individual.phenotips_patient_id = phenotips_patient_id
    individual.phenotips_eid = phenotips_eid
    individual.save()

    return create_json_response({
        individual.guid: {
            'phenotipsData': patient_json,
            'phenotipsPatientId': phenotips_patient_id,
            'phenotipsEid': phenotips_eid
        }
    })
Example #18
0
def _get_project_details(project, user):
    check_permissions(project, user)

    project_json = _get_json_for_project(project, user)

    families_by_guid, individuals_by_guid, samples_by_guid, analysis_groups_by_guid, locus_lists_by_guid = get_project_child_entities(
        project, user)

    project_json.update({
        'hasGeneSearch':
        True,
        'locusListGuids':
        locus_lists_by_guid.keys(),
        'variantTagTypes':
        get_project_variant_tag_types(project),
        'variantFunctionalTagTypes':
        get_json_for_variant_functional_data_tag_types(),
    })

    return {
        'projectsByGuid': {
            project.guid: project_json
        },
        'familiesByGuid': families_by_guid,
        'individualsByGuid': individuals_by_guid,
        'samplesByGuid': samples_by_guid,
        'locusListsByGuid': locus_lists_by_guid,
        'analysisGroupsByGuid': analysis_groups_by_guid,
    }
Example #19
0
def create_variant_note_handler(request, variant_guids):
    request_json = json.loads(request.body)
    save_as_gene_note = request_json.get('saveAsGeneNote')

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

    all_variant_guids = 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)

    # update saved_variants
    note = _create_variant_note(saved_variants, request_json, request.user)
    note_json = get_json_for_variant_note(note, add_variant_guids=False)
    note_json['variantGuids'] = all_variant_guids
    response = {
        'savedVariantsByGuid': {
            saved_variant.guid: {
                'noteGuids':
                [n.guid for n in saved_variant.variantnote_set.all()]
            }
            for saved_variant in saved_variants
        },
        'variantNotesByGuid': {
            note.guid: note_json
        },
    }

    if save_as_gene_note:
        main_transcript_id = saved_variants[
            0].selected_main_transcript_id or saved_variants[
                0].saved_variant_json['mainTranscriptId']
        gene_id = next(
            (gene_id for gene_id, transcripts in saved_variants[0].
             saved_variant_json['transcripts'].items() if any(
                 t['transcriptId'] == main_transcript_id
                 for t in transcripts)), None) if main_transcript_id else None
        GeneNote.objects.create(
            note=request_json.get('note'),
            gene_id=gene_id,
            created_by=request.user,
        )
        response['genesById'] = {
            gene_id: {
                'notes':
                get_json_for_gene_notes_by_gene_id([gene_id],
                                                   request.user)[gene_id],
            }
        }

    return create_json_response(response)
Example #20
0
def update_variant_main_transcript(request, variant_guid, transcript_id):
    saved_variant = SavedVariant.objects.get(guid=variant_guid)
    check_permissions(saved_variant.family.project, request.user, CAN_EDIT)

    saved_variant.selected_main_transcript_id = transcript_id
    saved_variant.save()

    return create_json_response({'savedVariantsByGuid': {variant_guid: {'selectedMainTranscriptId': transcript_id}}})
Example #21
0
def delete_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)
    delete_seqr_model(note)
    return create_json_response({variant_guid: {
        'notes': [get_json_for_variant_note(tag) for tag in saved_variant.variantnote_set.all()]
    }})
Example #22
0
def delete_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)
    delete_seqr_model(note)
    return create_json_response({'savedVariantsByGuid': {variant_guid: {
        'notes': [get_json_for_variant_note(tag) for tag in saved_variant.variantnote_set.all()]
    }}})
Example #23
0
def create_variant_note_handler(request, variant_guid):
    saved_variant = SavedVariant.objects.get(guid=variant_guid)
    check_permissions(saved_variant.project, request.user, CAN_VIEW)

    _create_variant_note(saved_variant, json.loads(request.body), request.user)

    return create_json_response({'savedVariantsByGuid': {variant_guid: {
        'notes': [get_json_for_variant_note(tag) for tag in saved_variant.variantnote_set.all()]
    }}})
Example #24
0
def update_project_categories_handler(request, project_guid):
    """Update ProjectCategories for the given project.

    Args:
        project_guid (string): GUID of the project that should be updated

    HTTP POST
        Request body - should contain the following json structure:
        {
            'form' : {
                'categories': a list of category GUIDs for the categories assigned to the given project
            }
        }

        Response body - will contain the following structure, representing the updated project,
            as well all categories in seqr:
            {
                'projectsByGuid':  {
                    <projectGuid1> : { ... <project key-value pairs> ... }
                }
                'projectCategoriesByGuid':  {
                    <projectCategoryGuid1> : { ... <category key-value pairs> ... }
                    <projectCategoryGuid2> : { ... <category key-value pairs> ... }
                }
            }
    """
    project = Project.objects.get(guid=project_guid)

    # check permissions
    check_permissions(project, request.user, CAN_EDIT)

    request_json = json.loads(request.body)

    if 'form' not in request_json:
        return create_json_response(
            {},
            status=400,
            reason="Invalid request: 'form' not in request_json")

    form_data = request_json['form']

    # project categories according to the UI
    current_category_guids = set(form_data['categories'])

    project_categories_by_guid = _update_project_categories(
        project, request.user, current_category_guids)

    projects_by_guid = {
        project.guid: _get_json_for_project(project, request.user)
    }

    return create_json_response({
        'projectsByGuid':
        projects_by_guid,
        'projectCategoriesByGuid':
        project_categories_by_guid,
    })
Example #25
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 #26
0
def update_mme_submission(request, individual_guid):
    """
    Create or update the submission for the given individual.
    """
    individual = Individual.objects.get(guid=individual_guid)
    check_permissions(individual.family.project, request.user)

    submission_json = json.loads(request.body)

    submission_json.pop('individualGuid', {})
    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')

    if not submission_json.get('patient', {}).get('id'):
        return create_json_response({}, status=400, reason='Patient id is 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:
            feature['zygosity'] = gene_variant['numAlt'] % 2
        if gene_variant.get('pos'):
            feature['variant'] = {
                'alternateBases': gene_variant['alt'],
                'referenceBases': gene_variant['ref'],
                'referenceName': gene_variant['chrom'],
                'start': gene_variant['pos'],
                'assembly': GENOME_VERSION_LOOKUP[gene_variant['genomeVersion']],
            }
        genomic_features.append(feature)

    submission_json['patient']['genomicFeatures'] = genomic_features
    submission_json['patient']['features'] = phenotypes

    response = requests.post(url=MME_ADD_INDIVIDUAL_URL, headers=MME_HEADERS, data=json.dumps(submission_json))

    if response.status_code not in (200, 409):
        try:
            response_json = response.json()
        except Exception:
            response_json = {}
        return create_json_response(response_json, status=response.status_code, reason=response.content)

    submitted_date = datetime.now()
    individual.mme_submitted_data = submission_json
    individual.mme_submitted_date = submitted_date
    individual.mme_deleted_date = None
    individual.mme_deleted_by = None
    individual.save()

    # search for new matches
    return _search_individual_matches(individual, request.user)
Example #27
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 #28
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 #29
0
def update_project_handler(request, project_guid):
    """Update project metadata - including one or more of these fields: name, description

    Args:
        project_guid (string): GUID of the project that should be updated

    HTTP POST
        Request body - should contain the following json structure:
        {
            'form' : {
                'name':  <project name>,
                'description': <project description>,
            }
        }

        Response body - will contain the following structure, representing the updated project:
            {
                'projectsByGuid':  {
                    <projectGuid1> : { ... <project key-value pairs> ... }
                }
            }

    """

    project = Project.objects.get(guid=project_guid)

    check_permissions(project, request.user, CAN_EDIT)

    request_json = json.loads(request.body)
    if 'form' not in request_json:
        return create_json_response(
            {},
            status=400,
            reason="Invalid request: 'form' not in request_json")

    form_data = request_json['form']
    if 'name' in form_data:
        project.name = form_data.get('name')
        project.save()
    if 'description' in form_data:
        project.description = form_data.get('description')
        project.save()

    # keep new seqr.Project model in sync with existing xbrowse_server.base.models - TODO remove this code after transition to new schema is finished
    _deprecated_update_original_project(project)

    return create_json_response({
        'projectsByGuid': {
            project.guid: _get_json_for_project(project, request.user)
        },
    })
Example #30
0
def search_individual_mme_matches(request, individual_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
    """

    individual = Individual.objects.get(guid=individual_guid)
    project = individual.family.project
    check_permissions(project, request.user)
    return _search_individual_matches(individual, request.user)
Example #31
0
def search_individual_mme_matches(request, individual_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
    """

    individual = Individual.objects.get(guid=individual_guid)
    project = individual.family.project
    check_permissions(project, request.user)
    return _search_individual_matches(individual, request.user)
Example #32
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_permissions(project, request.user, CAN_VIEW)
    request_json = json.loads(request.body)
    update_model_from_json(note, request_json, 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 #33
0
def update_family_analysed_by(request, family_guid):
    """Updates the specified field in the Family model.

    Args:
        family_guid (string): GUID of the family.
        field_name (string): Family model field name to update
    """

    family = Family.objects.get(guid=family_guid)
    check_permissions(family.project, request.user, CAN_EDIT)

    create_seqr_model(FamilyAnalysedBy, family=family, created_by=request.user)

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

    # TODO when variant search is rewritten for seqr models use that here
    base_project = find_matching_xbrowse_model(saved_variant.project)
    loaded_variant = get_datastore(base_project).get_single_variant(
        base_project.project_id,
        saved_variant.family.family_id,
        saved_variant.xpos,
        saved_variant.ref,
        saved_variant.alt,
    )

    return create_json_response({variant_guid: {'transcripts': _variant_transcripts(loaded_variant.annotation)}})
Example #35
0
def delete_variant_note_handler(request, variant_guid, note_guid):
    saved_variant = SavedVariant.objects.get(guid=variant_guid)
    check_permissions(saved_variant.family.project, request.user, CAN_VIEW)
    VariantNote.objects.get(guid=note_guid,
                            saved_variant=saved_variant).delete()
    return create_json_response({
        'savedVariantsByGuid': {
            variant_guid: {
                'notes': [
                    get_json_for_variant_note(tag)
                    for tag in saved_variant.variantnote_set.all()
                ]
            }
        }
    })
Example #36
0
def delete_variant_note_handler(request, variant_guids, note_guid):
    variant_guids = variant_guids.split(',')
    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_permissions(project, request.user, CAN_VIEW)
    note.delete()

    return create_json_response({
        'savedVariantsByGuid': {
            saved_variant.guid: {'noteGuids': [n.guid for n in saved_variant.variantnote_set.all()]}
            for saved_variant in SavedVariant.objects.filter(guid__in=variant_guids)
        },
        'variantNotesByGuid': {note_guid: None},
    })
Example #37
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 #38
0
def update_family_analysed_by(request, family_guid):
    """Updates the specified field in the Family model.

    Args:
        family_guid (string): GUID of the family.
        field_name (string): Family model field name to update
    """

    family = Family.objects.get(guid=family_guid)
    # analysed_by can be edited by anyone with access to the project
    check_permissions(family.project, request.user, CAN_VIEW)

    FamilyAnalysedBy.objects.create(family=family, created_by=request.user)

    return create_json_response(
        {family.guid: _get_json_for_family(family, request.user)})
Example #39
0
def update_family_analysed_by(request, family_guid):
    """Updates the specified field in the Family model.

    Args:
        family_guid (string): GUID of the family.
        field_name (string): Family model field name to update
    """

    family = Family.objects.get(guid=family_guid)
    check_permissions(family.project, request.user, CAN_EDIT)

    create_seqr_model(FamilyAnalysedBy, family=family, created_by=request.user)

    return create_json_response({
        family.guid: _get_json_for_family(family, request.user)
    })
def update_project_categories_handler(request, project_guid):
    """Update ProjectCategories for the given project.

    Args:
        project_guid (string): GUID of the project that should be updated

    HTTP POST
        Request body - should contain the following json structure:
        {
            'form' : {
                'categories': a list of category GUIDs for the categories assigned to the given project
            }
        }

        Response body - will contain the following structure, representing the updated project,
            as well all categories in seqr:
            {
                'projectsByGuid':  {
                    <projectGuid1> : { ... <project key-value pairs> ... }
                }
                'projectCategoriesByGuid':  {
                    <projectCategoryGuid1> : { ... <category key-value pairs> ... }
                    <projectCategoryGuid2> : { ... <category key-value pairs> ... }
                }
            }
    """
    project = Project.objects.get(guid=project_guid)

    # check permissions
    check_permissions(project, request.user, CAN_EDIT)

    request_json = json.loads(request.body)

    # project categories according to the UI
    current_category_guids = set(request_json['categories'])

    project_categories_by_guid = _update_project_categories(project, request.user, current_category_guids)

    projects_by_guid = {
        project.guid: _get_json_for_project(project, request.user)
    }

    return create_json_response({
        'projectsByGuid': projects_by_guid,
        'projectCategoriesByGuid': project_categories_by_guid,
    })
Example #41
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 #42
0
def update_family_fields_handler(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
    project = family.project

    check_permissions(project, request.user, CAN_EDIT)

    request_json = json.loads(request.body)
    update_family_from_json(family, request_json, user=request.user, allow_unknown_keys=True)

    return create_json_response({
        family.guid: _get_json_for_family(family, request.user)
    })
Example #43
0
def _get_project_details(project, user):
    check_permissions(project, user)

    project_json = _get_json_for_project(project, user)

    families_by_guid, individuals_by_guid, samples_by_guid, analysis_groups_by_guid, locus_lists_by_guid = get_project_child_entities(project, user)

    project_json.update({
        'hasGeneSearch': True,
        'locusListGuids': locus_lists_by_guid.keys(),
        'variantTagTypes': get_project_variant_tag_types(project),
        'variantFunctionalTagTypes': get_json_for_variant_functional_data_tag_types(),
    })

    return {
        'projectsByGuid': {project.guid: project_json},
        'familiesByGuid': families_by_guid,
        'individualsByGuid': individuals_by_guid,
        'samplesByGuid': samples_by_guid,
        'locusListsByGuid': locus_lists_by_guid,
        'analysisGroupsByGuid': analysis_groups_by_guid,
    }
Example #44
0
def _phenotips_view_handler(request, project_guid, individual_guid, url_template, permission_level=CAN_VIEW):
    """Requests the PhenoTips PDF for the given patient_id, and forwards PhenoTips' response to the client.

    Args:
        request: Django HTTP request object
        project_guid (string): project GUID for the seqr project containing this individual
        individual_guid (string): individual GUID for the seqr individual corresponding to the desired patient
    """

    project = Project.objects.get(guid=project_guid)
    check_permissions(project, request.user, CAN_VIEW)

    individual = Individual.objects.get(guid=individual_guid)
    _create_patient_if_missing(project, individual)
    _set_phenotips_patient_id_if_missing(project, individual)

    # query string forwarding needed for PedigreeEditor button
    query_string = request.META["QUERY_STRING"]
    url = url_template.format(patient_id=individual.phenotips_patient_id, query_string=query_string)

    auth_tuple = _get_phenotips_username_and_password(request.user, project, permissions_level=permission_level)

    return proxy_request(request, url, headers={}, auth_tuple=auth_tuple, host=settings.PHENOTIPS_SERVER)
Example #45
0
def update_project_handler(request, project_guid):
    """Update project metadata - including one or more of these fields: name, description

    Args:
        project_guid (string): GUID of the project that should be updated

    HTTP POST
        Request body - should contain the following json structure:
        {
            'form' : {
                'name':  <project name>,
                'description': <project description>,
            }
        }

        Response body - will contain the following structure, representing the updated project:
            {
                'projectsByGuid':  {
                    <projectGuid1> : { ... <project key-value pairs> ... }
                }
            }

    """

    project = Project.objects.get(guid=project_guid)

    check_permissions(project, request.user, CAN_EDIT)

    request_json = json.loads(request.body)
    update_project_from_json(project, request_json, allow_unknown_keys=True)

    return create_json_response({
        'projectsByGuid': {
            project.guid: _get_json_for_project(project, request.user)
        },
    })
Example #46
0
def update_mme_submission(request, individual_guid):
    """
    Create or update the submission for the given individual.
    """
    individual = Individual.objects.get(guid=individual_guid)
    project = individual.family.project
    check_permissions(project, request.user)

    submission_json = json.loads(request.body)

    submission_json.pop('individualGuid', {})
    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')

    if not submission_json.get('patient', {}).get('id'):
        return create_json_response({}, status=400, reason='Patient id is 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:
            feature['zygosity'] = gene_variant['numAlt'] % 2
        if gene_variant.get('pos'):
            feature['variant'] = {
                'alternateBases': gene_variant['alt'],
                'referenceBases': gene_variant['ref'],
                'referenceName': gene_variant['chrom'],
                'start': gene_variant['pos'],
                'assembly': gene_variant['genomeVersion'],
            }
        genomic_features.append(feature)

    submission_json['patient']['genomicFeatures'] = genomic_features
    submission_json['patient']['features'] = phenotypes

    response = requests.post(url=MME_ADD_INDIVIDUAL_URL, headers=MME_HEADERS, data=json.dumps(submission_json))

    if response.status_code not in (200, 409):
        try:
            response_json = response.json()
        except Exception:
            response_json = {}
        return create_json_response(response_json, status=response.status_code, reason=response.content)

    submitted_date = datetime.now()
    individual.mme_submitted_data = submission_json
    individual.mme_submitted_date = submitted_date
    individual.mme_deleted_date = None
    individual.mme_deleted_by = None
    individual.save()

    # update the project contact information if anything new was added
    new_contact_names = set(submission_json['patient']['contact']['name'].split(',')) - set(project.mme_primary_data_owner.split(','))
    new_contact_urls = set(submission_json['patient']['contact']['href'].replace('mailto:', '').split(',')) - set(project.mme_contact_url.replace('mailto:', '').split(','))
    updates = {}
    if new_contact_names:
        updates['mme_primary_data_owner'] = '{},{}'.format(project.mme_primary_data_owner, ','.join(new_contact_names))
    if new_contact_urls:
        updates['mme_contact_url'] = '{},{}'.format(project.mme_contact_url, ','.join(new_contact_urls))
    if updates:
        update_seqr_model(project, **updates)

    # search for new matches
    return _search_individual_matches(individual, request.user)
Example #47
0
def _check_results_permission(results_model, user):
    families = results_model.families.prefetch_related('project').all()
    projects = {family.project for family in families}
    for project in projects:
        check_permissions(project, user)