def saved_variant_data(request, project_guid, variant_guids=None): project = get_project_and_check_permissions(project_guid, request.user) family_guids = request.GET['families'].split(',') if request.GET.get('families') else None variant_guids = variant_guids.split(',') if variant_guids else None if family_guids: variant_query = SavedVariant.objects.filter(family__guid__in=family_guids) else: get_note_only = bool(request.GET.get('includeNoteVariants')) variant_query = SavedVariant.objects.filter(family__project=project, varianttag__isnull=get_note_only).distinct() if variant_guids: variant_query = variant_query.filter(guid__in=variant_guids) if variant_query.count() < 1: return create_json_response({}, status=404, reason='Variant {} not found'.format(', '.join(variant_guids))) response = get_json_for_saved_variants_with_tags(variant_query, add_details=True) discovery_tags = None if user_is_analyst(request.user): discovery_tags, discovery_response = get_json_for_discovery_tags(response['savedVariantsByGuid'].values()) response.update(discovery_response) variants = list(response['savedVariantsByGuid'].values()) genes = saved_variant_genes(variants) response['locusListsByGuid'] = _add_locus_lists([project], genes) if discovery_tags: _add_discovery_tags(variants, discovery_tags) response['genesById'] = genes return create_json_response(response)
def saved_variant_data(request, project_guid, variant_guids=None): project = get_project_and_check_permissions(project_guid, request.user) family_guids = request.GET['families'].split(',') if request.GET.get('families') else None variant_guids = variant_guids.split(',') if variant_guids else None if family_guids: variant_query = SavedVariant.objects.filter(family__guid__in=family_guids) else: variant_query = SavedVariant.objects.filter(family__project=project) if variant_guids: variant_query = variant_query.filter(guid__in=variant_guids) if variant_query.count() < 1: return create_json_response({}, status=404, reason='Variant {} not found'.format(', '.join(variant_guids))) discovery_tags_query = None if user_is_analyst(request.user): discovery_tags_query = Q() for variant in variant_query: discovery_tags_query |= Q(Q(variant_id=variant.variant_id) & ~Q(family_id=variant.family_id)) discovery_tags_query &= Q(family__project__projectcategory__name=ANALYST_PROJECT_CATEGORY) response = get_json_for_saved_variants_with_tags(variant_query, add_details=True, discovery_tags_query=discovery_tags_query) variants = list(response['savedVariantsByGuid'].values()) genes = saved_variant_genes(variants) response['locusListsByGuid'] = _add_locus_lists([project], genes) discovery_tags = response.pop('discoveryTags', None) if discovery_tags: _add_discovery_tags(variants, discovery_tags) response['genesById'] = genes return create_json_response(response)
def mme_details(request): submissions = MatchmakerSubmission.objects.filter(deleted_date__isnull=True).filter( individual__family__project__in=get_projects_user_can_view(request.user)) hpo_terms_by_id, genes_by_id, gene_symbols_to_ids = get_mme_genes_phenotypes_for_submissions(submissions) submission_json = get_json_for_matchmaker_submissions( submissions, additional_model_fields=['label'], all_parent_guids=True) submissions_by_guid = {s['submissionGuid']: s for s in submission_json} for submission in submissions: gene_variants = parse_mme_gene_variants(submission.genomic_features, gene_symbols_to_ids) submissions_by_guid[submission.guid].update({ 'phenotypes': parse_mme_features(submission.features, hpo_terms_by_id), 'geneVariants': gene_variants, 'geneSymbols': ','.join({genes_by_id.get(gv['geneId'], {}).get('geneSymbol') for gv in gene_variants}) }) response = { 'submissions': list(submissions_by_guid.values()), 'genesById': genes_by_id, } if user_is_analyst(request.user): response['metrics'] = get_mme_metrics() return create_json_response(response)
def _process_result(result, search): # Do not apply HGMD filters in shared searches for non-analyst users if not search.created_by and not user_is_analyst( user) and result['search'].get('pathogenicity', {}).get('hgmd'): result['search']['pathogenicity'] = { k: v for k, v in result['search']['pathogenicity'].items() if k != 'hgmd' }
def query_variants_handler(request, search_hash): """Search variants. """ page = int(request.GET.get('page') or 1) per_page = int(request.GET.get('per_page') or 100) sort = request.GET.get('sort') or XPOS_SORT_KEY if sort == PATHOGENICTY_SORT_KEY and user_is_analyst(request.user): sort = PATHOGENICTY_HGMD_SORT_KEY search_context = json.loads(request.body or '{}') try: results_model = _get_or_create_results_model(search_hash, search_context, request.user) except Exception as e: return create_json_response({'error': str(e)}, status=400, reason=str(e)) _check_results_permission(results_model, request.user) is_all_project_search = _is_all_project_family_search(search_context) variants, total_results = get_es_variants( results_model, sort=sort, page=page, num_results=per_page, skip_genotype_filter=is_all_project_search, user=request.user) response_context = {} if is_all_project_search and len(variants) == total_results: # For all project search only save the relevant families family_guids = set() for variant in variants: family_guids.update(variant['familyGuids']) families = results_model.families.filter(guid__in=family_guids) results_model.families.set(families) projects = Project.objects.filter(family__in=families).distinct() response_context = _get_projects_details(projects, request.user) response = _process_variants(variants or [], results_model.families.all(), request.user) response['search'] = _get_search_context(results_model) response['search']['totalResults'] = total_results response.update(response_context) return create_json_response(response)
def get_json_for_saved_searches(searches, user): is_analyst = user_is_analyst(user) def _process_result(result, search): # Do not apply HGMD filters in shared searches for non-analyst users if not search.created_by and not is_analyst and result['search'].get( 'pathogenicity', {}).get('hgmd'): result['search']['pathogenicity'] = { k: v for k, v in result['search']['pathogenicity'].items() if k != 'hgmd' } prefetch_related_objects(searches, 'created_by') return _get_json_for_models(searches, guid_key='savedSearchGuid', process_result=_process_result)
def _process_variants(variants, families, user): if not variants: return {'searchedVariants': variants} prefetch_related_objects(families, 'project') genes = saved_variant_genes(variants) projects = {family.project for family in families} locus_lists_by_guid = _add_locus_lists(projects, genes) response_json, _ = _get_saved_variants( variants, families, include_discovery_tags=user_is_analyst(user)) response_json.update({ 'searchedVariants': variants, 'genesById': genes, 'locusListsByGuid': locus_lists_by_guid, }) return response_json
def project_page_data(request, project_guid): """Returns a JSON object containing information used by the project page: :: json_response = { 'project': {..}, 'familiesByGuid': {..}, 'individualsByGuid': {..}, 'samplesByGuid': {..}, } Args: project_guid (string): GUID of the Project to retrieve data for. """ project = get_project_and_check_permissions(project_guid, request.user) update_project_from_json(project, {'last_accessed_date': timezone.now()}, request.user) is_analyst = user_is_analyst(request.user) response = _get_project_child_entities(project, request.user, is_analyst) project_json = _get_json_for_project(project, request.user, is_analyst=is_analyst) project_json['collaborators'] = get_json_for_project_collaborator_list( request.user, project) project_json['locusListGuids'] = list(response['locusListsByGuid'].keys()) project_json['detailsLoaded'] = True project_json.update(_get_json_for_variant_tag_types(project)) gene_ids = set() for tag in project_json['discoveryTags']: gene_ids.update(list(tag.get('transcripts', {}).keys())) for submission in response['mmeSubmissionsByGuid'].values(): gene_ids.update(submission['geneIds']) response.update({ 'projectsByGuid': { project_guid: project_json }, 'genesById': get_genes(gene_ids), }) return create_json_response(response)
def update_model_from_json(model_obj, json, user, allow_unknown_keys=False, immutable_keys=None, updated_fields=None, verbose=True): immutable_keys = (immutable_keys or []) + [ 'created_by', 'created_date', 'last_modified_date', 'id' ] internal_fields = model_obj._meta.internal_json_fields if hasattr( model_obj._meta, 'internal_json_fields') else [] if not updated_fields: updated_fields = set() for json_key, value in json.items(): orm_key = _to_snake_case(json_key) if orm_key in immutable_keys: if allow_unknown_keys: continue raise ValueError('Cannot edit field {}'.format(orm_key)) if allow_unknown_keys and not hasattr(model_obj, orm_key): continue if getattr(model_obj, orm_key) != value: if orm_key in internal_fields and not user_is_analyst(user): raise PermissionDenied( 'User {0} is not authorized to edit the internal field {1}' .format(user, orm_key)) updated_fields.add(orm_key) setattr(model_obj, orm_key, value) if updated_fields: model_obj.save() if verbose: log_model_update(logger, model_obj, user, 'update', updated_fields) return bool(updated_fields)
def _process_result(result, family): result['analysedBy'] = [{ 'createdBy': { 'fullName': ab.created_by.get_full_name(), 'email': ab.created_by.email, 'isAnalyst': user_is_analyst(ab.created_by) }, 'lastModifiedDate': ab.last_modified_date, } for ab in family.familyanalysedby_set.all()] pedigree_image = _get_pedigree_image_url(result.pop('pedigreeImage')) result['pedigreeImage'] = pedigree_image if add_individual_guids_field: result['individualGuids'] = [ i.guid for i in family.individual_set.all() ] if not result['displayName']: result['displayName'] = result['familyId'] if result['assignedAnalyst']: result['assignedAnalyst'] = { 'fullName': result['assignedAnalyst'].get_full_name(), 'email': result['assignedAnalyst'].email, } else: result['assignedAnalyst'] = None
def _get_json_for_models(models, nested_fields=None, user=None, is_analyst=None, process_result=None, guid_key=None, additional_model_fields=None): """Returns an array JSON representations of the given models. Args: models (array): Array of django models user (object): Django User object for determining whether to include restricted/internal-only fields nested_fields (array): Optional array of fields to get from the model that are nested on related objects process_result (lambda): Optional function to post-process a given model json guid_key (string): Optional key to use for the model's guid Returns: array: json objects """ if not models: return [] model_class = type(models[0]) fields = copy(model_class._meta.json_fields) if is_analyst is None: is_analyst = user and user_is_analyst(user) if is_analyst: fields += getattr(model_class._meta, 'internal_json_fields', []) if additional_model_fields: fields += additional_model_fields if 'created_by' in fields: prefetch_related_objects(models, 'created_by') for nested_field in nested_fields or []: if not nested_field.get('value'): prefetch_related_objects(models, '__'.join(nested_field['fields'][:-1])) results = [] for model in models: result = { _to_camel_case(field): getattr(model, field) for field in fields } for nested_field in (nested_fields or []): field_value = nested_field.get('value') if not field_value: field_value = model for field in nested_field['fields']: field_value = getattr(field_value, field) if field_value else None result[nested_field.get( 'key', _to_camel_case('_'.join( nested_field['fields'])))] = field_value if result.get('guid'): guid_key = guid_key or '{}{}Guid'.format( model_class.__name__[0].lower(), model_class.__name__[1:]) result[guid_key] = result.pop('guid') if result.get('createdBy'): result['createdBy'] = result['createdBy'].get_full_name( ) or result['createdBy'].email if process_result: process_result(result, model) results.append(result) return results
'date_joined', 'id' ] BOOL_USER_FIELDS = { 'is_superuser': False, 'is_active': True, } MODEL_USER_FIELDS = MAIN_USER_FIELDS + list(BOOL_USER_FIELDS.keys()) COMPUTED_USER_FIELDS = { 'is_anvil': lambda user, is_anvil=None, **kwargs: is_anvil_authenticated(user) if is_anvil is None else is_anvil, 'display_name': lambda user, **kwargs: user.get_full_name(), 'is_analyst': lambda user, analyst_users=None, **kwargs: user in analyst_users if analyst_users is not None else user_is_analyst(user), 'is_data_manager': lambda user, **kwargs: user_is_data_manager(user), 'is_pm': lambda user, pm_users=None, **kwargs: user in pm_users if pm_users is not None else user_is_pm(user), } DEFAULT_USER = {_to_camel_case(field): '' for field in MAIN_USER_FIELDS} DEFAULT_USER.update( {_to_camel_case(field): val for field, val in BOOL_USER_FIELDS.items()}) DEFAULT_USER.update( {_to_camel_case(field): False for field in COMPUTED_USER_FIELDS.keys()})
'username', 'email', 'first_name', 'last_name', 'last_login', 'date_joined', 'id' ] BOOL_USER_FIELDS = { 'is_superuser': False, 'is_active': True, } MODEL_USER_FIELDS = MAIN_USER_FIELDS + list(BOOL_USER_FIELDS.keys()) COMPUTED_USER_FIELDS = { 'is_anvil': lambda user, is_anvil=None: is_anvil_authenticated(user) if is_anvil is None else is_anvil, 'display_name': lambda user, **kwargs: user.get_full_name(), 'is_analyst': lambda user, **kwargs: user_is_analyst(user), 'is_data_manager': lambda user, **kwargs: user_is_data_manager(user), 'is_pm': lambda user, **kwargs: user_is_pm(user), } DEFAULT_USER = {_to_camel_case(field): '' for field in MAIN_USER_FIELDS} DEFAULT_USER.update( {_to_camel_case(field): val for field, val in BOOL_USER_FIELDS.items()}) DEFAULT_USER.update( {_to_camel_case(field): False for field in COMPUTED_USER_FIELDS.keys()})