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)})
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()] } })
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, ) }, })
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)})
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, )
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
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}}})
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) } })
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 {}, })
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) })
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
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)
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() ] } } })
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) }}})
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()] }})
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) }}})
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()] }}})
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)
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) }})
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}, })
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()] } }})
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) }, })
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)})
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) } })
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) } } })
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)}}, })
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 {}, })
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) }, })
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) } }, })
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)}}, })
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, })
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}}})
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})
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, ) }, })
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))