Exemple #1
0
def delete_project_locus_lists(request, project_guid):
    project = get_project_and_check_permissions(project_guid, request.user, CAN_EDIT)
    xbrowse_project = find_matching_xbrowse_model(project)
    request_json = json.loads(request.body)
    locus_lists = LocusList.objects.filter(guid__in=request_json['locusListGuids'])
    for locus_list in locus_lists:
        remove_perm(user_or_group=project.can_view_group, perm=CAN_VIEW, obj=locus_list)
        xbrowse_gene_list = find_matching_xbrowse_model(locus_list)
        if xbrowse_project and xbrowse_gene_list:
            BaseProjectGeneList.objects.filter(project=xbrowse_project, gene_list=xbrowse_gene_list).delete()

    return create_json_response({
        'locusListGuids': [locus_list['locusListGuid'] for locus_list in get_sorted_project_locus_lists(project, request.user)],
    })
Exemple #2
0
def delete_project_locus_lists(request, project_guid):
    project = get_project_and_check_permissions(project_guid, request.user, CAN_EDIT)
    xbrowse_project = find_matching_xbrowse_model(project)
    request_json = json.loads(request.body)
    locus_lists = LocusList.objects.filter(guid__in=request_json['locusListGuids'])
    for locus_list in locus_lists:
        remove_perm(user_or_group=project.can_view_group, perm=CAN_VIEW, obj=locus_list)
        xbrowse_gene_list = find_matching_xbrowse_model(locus_list)
        if xbrowse_project and xbrowse_gene_list:
            BaseProjectGeneList.objects.filter(project=xbrowse_project, gene_list=xbrowse_gene_list).delete()

    return create_json_response({
        'locusListGuids': [locus_list['locusListGuid'] for locus_list in get_sorted_project_locus_lists(project, request.user)],
    })
def _can_edit_entity_id(project, entity_id_key, entity_id):
    base_project = find_matching_xbrowse_model(project)
    if base_project.vcffile_set.count() and not base_project.has_elasticsearch_index():
        raise ValueError('Editing {} is disabled for projects which still use the mongo datastore'.format(entity_id_key))
    if project.is_mme_enabled:
        filter_key = 'family__family_id' if entity_id_key == 'family_id' else 'individual_id'
        individual_filter = {'family__project': project, filter_key: entity_id}
        if any(indiv for indiv in Individual.objects.filter(**individual_filter) if indiv.mme_submitted_date and not indiv.mme_deleted_date):
            raise ValueError('Editing {} is disabled for {} because it has matchmaker submissions'.format(
                entity_id_key, entity_id))
Exemple #4
0
def _save_pedigree_image_file(family, png_file_path):
    with open(png_file_path) as pedigree_image_file:
        family.pedigree_image.save(os.path.basename(png_file_path),
                                   File(pedigree_image_file))
        family.save()

    # update deprecated model
    base_family = find_matching_xbrowse_model(family)
    if base_family:
        with open(png_file_path) as pedigree_image_file:
            base_family.pedigree_image.save(os.path.basename(png_file_path),
                                            File(pedigree_image_file))
            base_family.save()
Exemple #5
0
def _can_edit_entity_id(project, entity_id_key, entity_id):
    base_project = find_matching_xbrowse_model(project)
    if not base_project.has_elasticsearch_index():
        raise ValueError(
            'Editing {} is disabled for projects which still use the mongo datastore'
            .format(entity_id_key))
    if project.is_mme_enabled and SEQR_ID_TO_MME_ID_MAP.find(
        {
            'project_id': project.deprecated_project_id,
            entity_id_key: entity_id
        }).count() > 0:
        raise ValueError(
            'Editing {} is disabled for {} because it has matchmaker submissions'
            .format(entity_id_key, entity_id))
Exemple #6
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)}})
Exemple #7
0
def _can_edit_entity_id(project, entity_id_key, entity_id):
    base_project = find_matching_xbrowse_model(project)
    if base_project.vcffile_set.count(
    ) and not base_project.has_elasticsearch_index():
        raise ValueError(
            'Editing {} is disabled for projects which still use the mongo datastore'
            .format(entity_id_key))
    if project.is_mme_enabled:
        filter_key = 'family__family_id' if entity_id_key == 'family_id' else 'individual_id'
        individual_filter = {'family__project': project, filter_key: entity_id}
        if any(indiv
               for indiv in Individual.objects.filter(**individual_filter)
               if indiv.mme_submitted_date and not indiv.mme_deleted_date):
            raise ValueError(
                'Editing {} is disabled for {} because it has matchmaker submissions'
                .format(entity_id_key, entity_id))
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)
        },
    })
Exemple #9
0
def update_individual_alignment_sample(request, individual_guid):
    """Create or update samples for the given dataset

    Args:
        request: Django request object
        individual_guid (string): GUID of the individual that should be updated

    HTTP POST
        Request body - should contain the following json structure:
        {
            'sampleType':  <"WGS", "WES", or "RNA"> (required)
            'datasetType': <"VARIANTS", or "ALIGN"> (required)
            'elasticsearchIndex': <String>
            'datasetPath': <String>
            'datasetName': <String>
            'ignoreExtraSamplesInCallset': <Boolean>
            'mappingFile': { 'uploadedFileId': <Id for temporary uploaded file> }
        }

        Response body - will contain the following structure:

    """
    individual = Individual.objects.get(guid=individual_guid)
    project = individual.family.project
    check_permissions(project, request.user, CAN_EDIT)

    request_json = json.loads(request.body)

    try:
        required_fields = ['sampleType', 'datasetFilePath']
        if any(field not in request_json for field in required_fields):
            raise ValueError(
                "request must contain fields: {}".format(', '.join(required_fields)))

        sample_type = request_json['sampleType']
        if sample_type not in {choice[0] for choice in Sample.SAMPLE_TYPE_CHOICES}:
            raise Exception("Sample type not supported: {}".format(sample_type))

        dataset_path = request_json['datasetFilePath']
        if not (dataset_path.endswith(".bam") or dataset_path.endswith(".cram")):
            raise Exception('BAM / CRAM file "{}" must have a .bam or .cram extension'.format(dataset_path))
        validate_alignment_dataset_path(dataset_path)

        sample, created = Sample.objects.get_or_create(
            individual=individual,
            dataset_type=Sample.DATASET_TYPE_READ_ALIGNMENTS,
            is_active=True,
        )
        sample.dataset_file_path = dataset_path
        sample.sample_type = sample_type
        sample.sample_id = dataset_path.split('/')[-1].split('.')[0]
        if created:
            sample.loaded_date = timezone.now()
        sample.save()

        # Deprecated update VCFFile records
        base_indiv = find_matching_xbrowse_model(individual)
        if base_indiv:
            base_indiv.bam_file_path = dataset_path
            base_indiv.save()

        response = {
            'samplesByGuid': {
                sample.guid: get_json_for_sample(sample, individual_guid=individual_guid, project_guid=project.guid)}
        }
        if created:
            response['individualsByGuid'] = {
                individual.guid: {'sampleGuids': [s.guid for s in individual.sample_set.all()]}
            }
        return create_json_response(response)
    except Exception as e:
        return create_json_response({}, status=400, reason=e.message or str(e))
Exemple #10
0
def _can_edit_entity_id(project, entity_id_key):
    base_project = find_matching_xbrowse_model(project)
    if base_project.vcffile_set.count() and not base_project.has_elasticsearch_index():
        raise ValueError('Editing {} is disabled for projects which still use the mongo datastore'.format(entity_id_key))
    def handle(self, *args, **options):
        from_project = Project.objects.get(guid=options['from_project'])
        to_project = Project.objects.get(guid=options['to_project'])
        to_base_project = find_matching_xbrowse_model(to_project)
        family_ids = options['family_ids']
        families = Family.objects.filter(project=from_project,
                                         family_id__in=family_ids)
        print('Found {} out of {} families. No match for: {}.'.format(
            len(families), len(set(family_ids)),
            set(family_ids) - set([f.family_id for f in families])))

        for f in families:
            print("==> Moving {}".format(f))
            for seqr_individual in f.individual_set.all():
                base_individual = find_matching_xbrowse_model(seqr_individual)
                base_individual.project = to_base_project
                base_individual.save()
                # Update individuals in phenotips
                if _phenotips_patient_exists(seqr_individual):
                    # make sure phenotips_patient_id is up to date
                    data_json = _get_patient_data(
                        from_project,
                        seqr_individual,
                    )

                    seqr_individual.phenotips_patient_id = data_json["id"]
                    seqr_individual.save()

                    # update permissions
                    phenotips_readonly_username, _ = _get_phenotips_uname_and_pwd_for_project(
                        to_project.phenotips_user_id, read_only=True)
                    _add_user_to_patient(phenotips_readonly_username,
                                         seqr_individual.phenotips_patient_id,
                                         allow_edit=False)

                    phenotips_readwrite_username, _ = _get_phenotips_uname_and_pwd_for_project(
                        to_project.phenotips_user_id, read_only=False)
                    _add_user_to_patient(phenotips_readwrite_username,
                                         seqr_individual.phenotips_patient_id,
                                         allow_edit=True)

                # Update individuals samples/ VCFs
                for from_vcf_file in base_individual.vcf_files.all():
                    to_vcf_file, _ = VCFFile.objects.get_or_create(
                        project=to_base_project,
                        elasticsearch_index=from_vcf_file.elasticsearch_index,
                        file_path=from_vcf_file.file_path,
                        dataset_type=from_vcf_file.dataset_type,
                        sample_type=from_vcf_file.sample_type,
                        loaded_date=from_vcf_file.loaded_date,
                    )
                    base_individual.vcf_files.add(to_vcf_file)
                    base_individual.vcf_files.remove(from_vcf_file)

            # Update variant tags/ notes
            saved_variants = SavedVariant.objects.filter(family=f)
            for variant_tag in VariantTag.objects.filter(
                    saved_variant__in=saved_variants).select_related(
                        'variant_tag_type'):
                if variant_tag.variant_tag_type.project:
                    to_tag_type, created = get_or_create_seqr_model(
                        VariantTagType,
                        project=to_project,
                        name=variant_tag.variant_tag_type.name)
                    if created:
                        update_seqr_model(
                            to_tag_type,
                            category=variant_tag.variant_tag_type.category,
                            description=variant_tag.variant_tag_type.
                            description,
                            color=variant_tag.variant_tag_type.color,
                            order=variant_tag.variant_tag_type.order,
                        )
                    update_seqr_model(variant_tag,
                                      variant_tag_type=to_tag_type)
                else:
                    to_project_tag, created = ProjectTag.objects.get_or_create(
                        project=to_base_project,
                        tag=variant_tag.variant_tag_type.name)
                    if created:
                        to_project_tag.category = variant_tag.variant_tag_type.category
                        to_project_tag.title = variant_tag.variant_tag_type.description
                        to_project_tag.color = variant_tag.variant_tag_type.color
                        to_project_tag.order = variant_tag.variant_tag_type.order
                        to_project_tag.save()
                    variant_tag.project_tag = to_project_tag
                    variant_tag.save()

            base_family = find_matching_xbrowse_model(f)
            for note in BaseVariantNote.objects.filter(family=base_family):
                note.project = to_base_project
                note.save()

            # Update families
            update_seqr_model(f, project=to_project)

        print("Done.")
Exemple #12
0
def update_analysis_group_handler(request,
                                  project_guid,
                                  analysis_group_guid=None):
    project = get_project_and_check_permissions(project_guid,
                                                request.user,
                                                permission_level=CAN_EDIT)

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

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

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

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

    return create_json_response({
        'analysisGroupsByGuid': {
            analysis_group.guid:
            get_json_for_analysis_group(analysis_group,
                                        project_guid=project_guid)
        },
    })
Exemple #13
0
def add_alignment_dataset_handler(request, project_guid):
    """Create or update samples for the given dataset

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

    HTTP POST
        Request body - should contain the following json structure:
        {
            'sampleType':  <"WGS", "WES", or "RNA"> (required)
            'datasetType': <"VARIANTS", or "ALIGN"> (required)
            'elasticsearchIndex': <String>
            'datasetPath': <String>
            'datasetName': <String>
            'ignoreExtraSamplesInCallset': <Boolean>
            'mappingFile': { 'uploadedFileId': <Id for temporary uploaded file> }
        }

        Response body - will contain the following structure:

    """
    project = get_project_and_check_permissions(project_guid,
                                                request.user,
                                                permission_level=CAN_EDIT)
    request_json = json.loads(request.body)

    try:
        required_fields = ['sampleType', 'mappingFile']
        if any(field not in request_json for field in required_fields):
            raise ValueError("request must contain fields: {}".format(
                ', '.join(required_fields)))

        sample_type = request_json['sampleType']
        if sample_type not in {
                choice[0]
                for choice in Sample.SAMPLE_TYPE_CHOICES
        }:
            raise Exception(
                "Sample type not supported: {}".format(sample_type))
        mapping_file_id = request_json['mappingFile']['uploadedFileId']

        sample_id_to_individual_id_mapping = {}
        sample_dataset_path_mapping = {}
        for individual_id, dataset_path in load_uploaded_mapping_file(
                mapping_file_id).items():
            if not (dataset_path.endswith(".bam")
                    or dataset_path.endswith(".cram")):
                raise Exception(
                    'BAM / CRAM file "{}" must have a .bam or .cram extension'.
                    format(dataset_path))
            validate_alignment_dataset_path(dataset_path)
            sample_id = dataset_path.split('/')[-1].split('.')[0]
            sample_id_to_individual_id_mapping[sample_id] = individual_id
            sample_dataset_path_mapping[sample_id] = dataset_path

        matched_sample_id_to_sample_record = match_sample_ids_to_sample_records(
            project=project,
            sample_ids=sample_id_to_individual_id_mapping.keys(),
            sample_type=sample_type,
            dataset_type=Sample.DATASET_TYPE_READ_ALIGNMENTS,
            sample_id_to_individual_id_mapping=
            sample_id_to_individual_id_mapping,
        )

        unmatched_samples = set(
            sample_id_to_individual_id_mapping.keys()) - set(
                matched_sample_id_to_sample_record.keys())
        if len(unmatched_samples) > 0:
            raise Exception(
                'The following Individual IDs do not exist: {}'.format(
                    ", ".join(unmatched_samples)))

        _update_samples(
            matched_sample_id_to_sample_record,
            sample_dataset_path_mapping=sample_dataset_path_mapping)

    except Exception as e:
        traceback.print_exc()
        return create_json_response({'errors': [e.message or str(e)]},
                                    status=400)

    if not matched_sample_id_to_sample_record:
        return create_json_response({'samplesByGuid': {}})

    # Deprecated update VCFFile records
    for sample in matched_sample_id_to_sample_record.values():
        base_indiv = find_matching_xbrowse_model(sample.individual)
        if base_indiv:
            base_indiv.bam_file_path = sample.dataset_file_path
            base_indiv.save()

    return create_json_response(
        _get_samples_json(matched_sample_id_to_sample_record, project_guid))