Ejemplo n.º 1
0
def variants(institute_id, case_name):
    """Display a list of SNV variants."""
    page = int(Markup.escape(request.form.get("page", "1")))
    category = "snv"
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    variant_type = request.args.get("variant_type", "clinical")
    variants_stats = store.case_variants_count(case_obj["_id"], institute_id, variant_type, False)

    if request.form.get("hpo_clinical_filter"):
        case_obj["hpo_clinical_filter"] = True

    user_obj = store.user(current_user.email)
    if request.method == "POST":
        if "dismiss_submit" in request.form:  # dismiss a list of variants
            controllers.dismiss_variant_list(
                store,
                institute_obj,
                case_obj,
                "variant.variant",
                request.form.getlist("dismiss"),
                request.form.getlist("dismiss_choices"),
            )

        form = controllers.populate_filters_form(
            store, institute_obj, case_obj, user_obj, category, request.form
        )
    else:
        form = FiltersForm(request.args)
        # set form variant data type the first time around
        form.variant_type.data = variant_type
        # set chromosome to all chromosomes
        form.chrom.data = request.args.get("chrom", "")

        if form.gene_panels.data == [] and variant_type == "clinical":
            form.gene_panels.data = controllers.case_default_panels(case_obj)

    # populate filters dropdown
    available_filters = list(store.filters(institute_id, category))
    form.filters.choices = [
        (filter.get("_id"), filter.get("display_name")) for filter in available_filters
    ]
    # Populate chromosome select choices
    controllers.populate_chrom_choices(form, case_obj)

    # populate available panel choices
    form.gene_panels.choices = controllers.gene_panel_choices(store, institute_obj, case_obj)

    # update status of case if visited for the first time
    controllers.activate_case(store, institute_obj, case_obj, current_user)

    # upload gene panel if symbol file exists
    if request.files:
        file = request.files[form.symbol_file.name]

    if request.files and file and file.filename != "":
        LOG.debug("Upload file request files: {0}".format(request.files.to_dict()))
        try:
            stream = io.StringIO(file.stream.read().decode("utf-8"), newline=None)
        except UnicodeDecodeError as error:
            flash("Only text files are supported!", "warning")
            return redirect(request.referrer)

        hgnc_symbols_set = set(form.hgnc_symbols.data)
        LOG.debug("Symbols prior to upload: {0}".format(hgnc_symbols_set))
        new_hgnc_symbols = controllers.upload_panel(store, institute_id, case_name, stream)
        hgnc_symbols_set.update(new_hgnc_symbols)
        form.hgnc_symbols.data = hgnc_symbols_set
        # reset gene panels
        form.gene_panels.data = ""

    controllers.update_form_hgnc_symbols(store, case_obj, form)

    cytobands = store.cytoband_by_chrom(case_obj.get("genome_build"))

    variants_query = store.variants(case_obj["_id"], query=form.data, category=category)
    result_size = store.count_variants(case_obj["_id"], form.data, None, category)

    if request.form.get("export"):
        return controllers.download_variants(store, case_obj, variants_query)

    data = controllers.variants(
        store, institute_obj, case_obj, variants_query, result_size, page, query_form=form.data
    )
    expand_search = request.method == "POST" and request.form.get("expand_search") in [
        "True",
        "",
    ]
    return dict(
        institute=institute_obj,
        case=case_obj,
        form=form,
        filters=available_filters,
        manual_rank_options=MANUAL_RANK_OPTIONS,
        dismiss_variant_options=DISMISS_VARIANT_OPTIONS,
        cancer_tier_options=CANCER_TIER_OPTIONS,
        severe_so_terms=SEVERE_SO_TERMS,
        cytobands=cytobands,
        page=page,
        expand_search=expand_search,
        result_size=result_size,
        total_variants=variants_stats.get(variant_type, {}).get(category, "NA"),
        **data,
    )
Ejemplo n.º 2
0
def cancer_sv_variants(institute_id, case_name):
    """Display a list of cancer structural variants."""

    page = int(Markup.escape(request.form.get("page", "1")))
    variant_type = Markup.escape(request.args.get("variant_type", "clinical"))
    category = "cancer_sv"
    # Define case and institute objects
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    variants_stats = store.case_variants_count(case_obj["_id"], institute_id, variant_type, False)

    if request.form.get("hpo_clinical_filter"):
        case_obj["hpo_clinical_filter"] = True

    if request.form.getlist("dismiss"):  # dismiss a list of variants
        controllers.dismiss_variant_list(
            store,
            institute_obj,
            case_obj,
            "variant.sv_variant",
            request.form.getlist("dismiss"),
            request.form.getlist("dismiss_choices"),
        )

    # update status of case if visited for the first time
    controllers.activate_case(store, institute_obj, case_obj, current_user)
    form = controllers.populate_sv_filters_form(store, institute_obj, case_obj, category, request)

    # populate filters dropdown
    available_filters = list(store.filters(institute_obj["_id"], category))
    form.filters.choices = [
        (filter.get("_id"), filter.get("display_name")) for filter in available_filters
    ]

    # Populate chromosome select choices
    controllers.populate_chrom_choices(form, case_obj)

    genome_build = "38" if "38" in str(case_obj.get("genome_build")) else "37"
    cytobands = store.cytoband_by_chrom(genome_build)

    controllers.update_form_hgnc_symbols(store, case_obj, form)

    variants_query = store.variants(case_obj["_id"], category=category, query=form.data)

    result_size = store.count_variants(case_obj["_id"], form.data, None, category)

    # if variants should be exported
    if request.form.get("export"):
        return controllers.download_variants(store, case_obj, variants_query)

    data = controllers.sv_variants(
        store, institute_obj, case_obj, variants_query, result_size, page
    )
    expand_search = request.method == "POST" and request.form.get("expand_search") in [
        "True",
        "",
    ]
    return dict(
        institute=institute_obj,
        case=case_obj,
        dismiss_variant_options={
            **DISMISS_VARIANT_OPTIONS,
            **CANCER_SPECIFIC_VARIANT_DISMISS_OPTIONS,
        },
        variant_type=variant_type,
        form=form,
        filters=available_filters,
        severe_so_terms=SEVERE_SO_TERMS,
        cancer_tier_options=CANCER_TIER_OPTIONS,
        manual_rank_options=MANUAL_RANK_OPTIONS,
        cytobands=cytobands,
        page=page,
        expand_search=expand_search,
        result_size=result_size,
        total_variants=variants_stats.get(variant_type, {}).get(category, "NA"),
        **data,
    )
Ejemplo n.º 3
0
def str_variants(institute_id, case_name):
    """Display a list of STR variants."""
    page = int(Markup.escape(request.form.get("page", "1")))
    variant_type = Markup.escape(request.args.get("variant_type", "clinical"))
    category = "str"

    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    variants_stats = store.case_variants_count(case_obj["_id"], institute_id, variant_type, False)

    user_obj = store.user(current_user.email)

    if request.method == "POST":
        form = controllers.populate_filters_form(
            store, institute_obj, case_obj, user_obj, category, request.form
        )
    else:
        form = StrFiltersForm(request.args)

        if form.gene_panels.data == [] and variant_type == "clinical":
            form.gene_panels.data = controllers.case_default_panels(case_obj)

        # set form variant data type the first time around
        form.variant_type.data = variant_type
        # set chromosome to all chromosomes
        form.chrom.data = request.args.get("chrom", "")

    # populate filters dropdown
    available_filters = list(store.filters(institute_id, category))
    form.filters.choices = [
        (filter.get("_id"), filter.get("display_name")) for filter in available_filters
    ]

    # Populate chromosome select choices
    controllers.populate_chrom_choices(form, case_obj)

    # populate available panel choices
    form.gene_panels.choices = controllers.gene_panel_choices(store, institute_obj, case_obj)

    controllers.activate_case(store, institute_obj, case_obj, current_user)

    cytobands = store.cytoband_by_chrom(case_obj.get("genome_build"))

    query = form.data
    query["variant_type"] = variant_type

    variants_query = store.variants(case_obj["_id"], category=category, query=query).sort(
        [
            ("str_repid", pymongo.ASCENDING),
            ("chromosome", pymongo.ASCENDING),
            ("position", pymongo.ASCENDING),
        ]
    )

    result_size = store.count_variants(case_obj["_id"], query, None, category)

    if request.form.get("export"):
        return controllers.download_str_variants(case_obj, variants_query)

    data = controllers.str_variants(
        store, institute_obj, case_obj, variants_query, result_size, page
    )
    return dict(
        institute=institute_obj,
        case=case_obj,
        dismiss_variant_options=DISMISS_VARIANT_OPTIONS,
        variant_type=variant_type,
        manual_rank_options=MANUAL_RANK_OPTIONS,
        cytobands=cytobands,
        form=form,
        page=page,
        filters=available_filters,
        expand_search=str(request.method == "POST"),
        result_size=result_size,
        total_variants=variants_stats.get(variant_type, {}).get(category, "NA"),
        **data,
    )
Ejemplo n.º 4
0
def cancer_variants(institute_id, case_name):
    """Show cancer variants overview."""
    category = "cancer"
    variant_type = Markup.escape(request.args.get("variant_type", "clinical"))
    institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
    variants_stats = store.case_variants_count(case_obj["_id"], institute_id, variant_type, False)

    user_obj = store.user(current_user.email)
    if request.method == "POST":
        if "dismiss_submit" in request.form:  # dismiss a list of variants
            controllers.dismiss_variant_list(
                store,
                institute_obj,
                case_obj,
                "variant.variant",
                request.form.getlist("dismiss"),
                request.form.getlist("dismiss_choices"),
            )

        form = controllers.populate_filters_form(
            store, institute_obj, case_obj, user_obj, category, request.form
        )

        # if user is not loading an existing filter, check filter form
        if (
            request.form.get("load_filter") is None
            and request.form.get("audit_filter") is None
            and form.validate_on_submit() is False
        ):
            # Flash a message with errors
            for field, err_list in form.errors.items():
                for err in err_list:
                    flash(f"Content of field '{field}' does not have a valid format", "warning")
            # And do not submit the form
            return redirect(
                url_for(
                    ".cancer_variants",
                    institute_id=institute_id,
                    case_name=case_name,
                    expand_search=True,
                )
            )
        page = int(Markup.escape(request.form.get("page", "1")))

    else:
        page = int(Markup.escape(request.args.get("page", "1")))
        form = CancerFiltersForm(request.args)
        # set chromosome to all chromosomes
        form.chrom.data = request.args.get("chrom", "")
        if form.gene_panels.data == []:
            form.gene_panels.data = controllers.case_default_panels(case_obj)

    # update status of case if visited for the first time
    controllers.activate_case(store, institute_obj, case_obj, current_user)

    # populate filters dropdown
    available_filters = list(store.filters(institute_id, category))
    form.filters.choices = [
        (filter.get("_id"), filter.get("display_name")) for filter in available_filters
    ]

    # Populate chromosome select choices
    controllers.populate_chrom_choices(form, case_obj)

    form.gene_panels.choices = controllers.gene_panel_choices(store, institute_obj, case_obj)
    genome_build = "38" if "38" in str(case_obj.get("genome_build")) else "37"
    cytobands = store.cytoband_by_chrom(genome_build)

    controllers.update_form_hgnc_symbols(store, case_obj, form)

    variants_query = store.variants(
        case_obj["_id"], category="cancer", query=form.data, build=genome_build
    )
    result_size = store.count_variants(case_obj["_id"], form.data, None, category)

    if request.form.get("export"):
        return controllers.download_variants(store, case_obj, variants_query)

    data = controllers.cancer_variants(
        store,
        institute_id,
        case_name,
        variants_query,
        result_size,
        form,
        page=page,
    )
    expand_search = request.method == "POST" and request.form.get("expand_search") in [
        "True",
        "",
    ]
    return dict(
        variant_type=variant_type,
        cytobands=cytobands,
        filters=available_filters,
        dismiss_variant_options={
            **DISMISS_VARIANT_OPTIONS,
            **CANCER_SPECIFIC_VARIANT_DISMISS_OPTIONS,
        },
        expand_search=expand_search,
        result_size=result_size,
        total_variants=variants_stats.get(variant_type, {}).get(category, "NA"),
        **data,
    )
Ejemplo n.º 5
0
def variants(
    user: str,
    case_id: str,
    status: list,
    older_than: int,
    analysis_type: list,
    rank_threshold: int,
    variants_threshold: int,
    keep_ctg: list,
    dry_run: bool,
) -> None:
    """Delete variants for one or more cases"""

    user_obj = store.user(user)
    if user_obj is None:
        click.echo(f"Could not find a user with email '{user}' in database")
        return

    total_deleted = 0
    items_name = "deleted variants"
    if dry_run:
        click.echo("--------------- DRY RUN COMMAND ---------------")
        items_name = "estimated deleted variants"
    else:
        click.confirm(
            "Variants are going to be deleted from database. Continue?",
            abort=True)

    case_query = store.build_case_query(case_id, status, older_than,
                                        analysis_type)
    # Estimate the average size of a variant document in database
    avg_var_size = store.collection_stats("variant").get("avgObjSize",
                                                         0)  # in bytes

    # Get all cases where case_query applies
    n_cases = store.case_collection.count_documents(case_query)
    cases = store.cases(query=case_query)
    filters = (
        f"Rank-score threshold:{rank_threshold}, case n. variants threshold:{variants_threshold}."
    )
    click.echo("\t".join(DELETE_VARIANTS_HEADER))
    for nr, case in enumerate(cases, 1):
        case_id = case["_id"]
        institute_id = case["owner"]
        case_n_variants = store.variant_collection.count_documents(
            {"case_id": case_id})
        # Skip case if user provided a number of variants to keep and this number is less than total number of case variants
        if variants_threshold and case_n_variants < variants_threshold:
            continue
        # Get evaluated variants for the case that haven't been dismissed
        case_evaluated = store.evaluated_variants(case_id=case_id,
                                                  institute_id=institute_id)
        evaluated_not_dismissed = [
            variant["_id"] for variant in case_evaluated
            if "dismiss_variant" not in variant
        ]
        # Do not remove variants that are either pinned, causative or evaluated not dismissed
        variants_to_keep = (case.get("suspects", []) +
                            case.get("causatives", []) +
                            evaluated_not_dismissed or [])
        variants_query = store.delete_variants_query(case_id, variants_to_keep,
                                                     rank_threshold, keep_ctg)

        if dry_run:
            # Just print how many variants would be removed for this case
            remove_n_variants = store.variant_collection.count_documents(
                variants_query)
            total_deleted += remove_n_variants
            click.echo("\t".join([
                str(nr),
                str(n_cases),
                case["owner"],
                case["display_name"],
                case_id,
                case.get("track", ""),
                str(case["analysis_date"]),
                case.get("status", ""),
                str(case.get("is_research", "")),
                str(case_n_variants),
                str(remove_n_variants),
            ]))
            continue

        # delete variants specified by variants_query
        result = store.variant_collection.delete_many(variants_query)
        total_deleted += result.deleted_count
        click.echo("\t".join([
            str(nr),
            str(n_cases),
            case["owner"],
            case["display_name"],
            case_id,
            case.get("track", ""),
            str(case["analysis_date"]),
            case.get("status", ""),
            str(case.get("is_research", "")),
            str(case_n_variants),
            str(result.deleted_count),
        ]))

        # Create event in database
        institute_obj = store.institute(case["owner"])
        with current_app.test_request_context("/cases"):
            url = url_for(
                "cases.case",
                institute_id=institute_obj["_id"],
                case_name=case["display_name"],
            )
            store.remove_variants_event(
                institute=institute_obj,
                case=case,
                user=user_obj,
                link=url,
                content=filters,
            )

        # Update case variants count
        store.case_variants_count(case_id, institute_obj["_id"], True)

    click.echo(f"Total {items_name}: {total_deleted}")
    click.echo(
        f"Estimated space freed (GB): {round((total_deleted * avg_var_size) / BYTES_IN_ONE_GIGABYTE, 4)}"
    )