Exemplo n.º 1
0
def causatives(institute_id):
    institute_obj = institute_and_case(store, institute_id)
    query = request.args.get('query', '')
    hgnc_id = None
    if '|' in query:
        # filter accepts an array of IDs. Provide an array with one ID element
        try:
            hgnc_id = [int(query.split(' | ', 1)[0])]
        except ValueError:
            flash('Provided gene info could not be parsed!', 'warning')

    variants = store.check_causatives(institute_obj=institute_obj,
                                      limit_genes=hgnc_id)
    if variants:
        variants.sort("hgnc_symbols", pymongo.ASCENDING)
    all_variants = {}
    all_cases = {}
    for variant_obj in variants:
        if variant_obj['case_id'] not in all_cases:
            case_obj = store.case(variant_obj['case_id'])
            all_cases[variant_obj['case_id']] = case_obj
        else:
            case_obj = all_cases[variant_obj['case_id']]

        if variant_obj['variant_id'] not in all_variants:
            # capture ACMG classification for this variant
            if isinstance(variant_obj.get('acmg_classification'), int):
                acmg_code = ACMG_MAP[variant_obj['acmg_classification']]
                variant_obj['acmg_classification'] = ACMG_COMPLETE_MAP[
                    acmg_code]

            all_variants[variant_obj['variant_id']] = []
        all_variants[variant_obj['variant_id']].append((case_obj, variant_obj))

    return dict(institute=institute_obj, variant_groups=all_variants)
Exemplo n.º 2
0
def panel(panel_id):
    """Display (and add pending updates to) a specific gene panel."""
    panel_obj = store.gene_panel(panel_id) or store.panel(panel_id)
    if request.method == 'POST':
        raw_hgnc_id = request.form['hgnc_id']
        if '|' in raw_hgnc_id:
            raw_hgnc_id = raw_hgnc_id.split(' | ', 1)[0]
        hgnc_id = int(raw_hgnc_id)
        action = request.form['action']

        if action == 'add':
            panel_gene = controllers.existing_gene(store, panel_obj, hgnc_id)
            if panel_gene:
                flash("gene already in panel: {}".format(panel_gene['symbol']),
                      'warning')
            else:
                # ask user to fill-in more information about the gene
                return redirect(
                    url_for('.gene_edit', panel_id=panel_id, hgnc_id=hgnc_id))
        elif action == 'delete':
            log.debug("marking gene to be deleted: %s", hgnc_id)
            store.add_pending(panel_obj, hgnc_id, action='delete')

    data = controllers.panel(store, panel_obj)
    if request.args.get('case_id'):
        data['case'] = store.case(request.args['case_id'])
    if request.args.get('institute_id'):
        data['institute'] = store.institute(request.args['institute_id'])
    return data
Exemplo n.º 3
0
def get_timeline_data(limit):
    """Retrieve chronologially ordered events from the database to display them in the timeline page

    Args:
        limit(str): for instance "50" to display last 50 events. "-1" to display all events

    Returns:
        timeline_results(dict): dictionary containing timeline data
    """
    timeline_results = []
    results = store.user_timeline(current_user.email, int(limit))
    for eventg in results:  # Add links to cases pages
        case_obj = store.case(case_id=eventg["_id"]["case_id"])
        if case_obj is None:
            continue
        # Some events are captured both for case and variant. Display them only once (for the variant)
        if (eventg["_id"].get("category") == "case"
                and eventg["_id"].get("verb") in VAR_SPECIFIC_EVENTS):
            continue
        # Build link to case page
        eventg["_id"]["case_name"] = case_obj.get("display_name")
        eventg["_id"]["link"] = url_for(
            "cases.case",
            institute_id=eventg["_id"]["institute"],
            case_name=case_obj["display_name"],
        )
        timeline_results.append(eventg)
    return timeline_results
Exemplo n.º 4
0
def get_sanger_unevaluated(store, institute_id, user_id):
    """Get all variants for an institute having Sanger validations ordered but still not evaluated

    Args:
        store(scout.adapter.MongoAdapter)
        institute_id(str)

    Returns:
        unevaluated: a list that looks like this: [ {'case1': [varID_1, varID_2, .., varID_n]}, {'case2' : [varID_1, varID_2, .., varID_n]} ],
                     where the keys are case_ids and the values are lists of variants with Sanger ordered but not yet validated

    """

    # Retrieve a list of ids for variants with Sanger ordered grouped by case from the 'event' collection
    # This way is much faster than querying over all variants in all cases of an institute
    sanger_ordered_by_case = store.sanger_ordered(institute_id, user_id)
    unevaluated = []

    # for each object where key==case and value==[variant_id with Sanger ordered]
    for item in sanger_ordered_by_case:
        case_id = item["_id"]
        # Get the case to collect display name
        case_obj = store.case(case_id=case_id)

        if not case_obj:  # the case might have been removed
            continue

        case_display_name = case_obj.get("display_name")

        # List of variant document ids
        varid_list = item["vars"]

        unevaluated_by_case = {}
        unevaluated_by_case[case_display_name] = []

        for var_id in varid_list:
            # For each variant with sanger validation ordered
            variant_obj = store.variant(document_id=var_id, case_id=case_id)

            # Double check that Sanger was ordered (and not canceled) for the variant
            if (
                variant_obj is None
                or variant_obj.get("sanger_ordered") is None
                or variant_obj.get("sanger_ordered") is False
            ):
                continue

            validation = variant_obj.get("validation", "not_evaluated")

            # Check that the variant is not evaluated
            if validation in ["True positive", "False positive"]:
                continue

            unevaluated_by_case[case_display_name].append(variant_obj["_id"])

        # If for a case there is at least one Sanger validation to evaluate add the object to the unevaluated objects list
        if len(unevaluated_by_case[case_display_name]) > 0:
            unevaluated.append(unevaluated_by_case)

    return unevaluated
Exemplo n.º 5
0
def gene_variants(store,
                  pymongo_cursor,
                  variant_count,
                  institute_id,
                  page=1,
                  per_page=50):
    """Pre-process list of variants."""

    skip_count = per_page * max(page - 1, 0)
    more_variants = True if variant_count > (skip_count + per_page) else False
    variant_res = pymongo_cursor.skip(skip_count).limit(per_page)
    my_institutes = set(inst["_id"]
                        for inst in user_institutes(store, current_user))
    variants = []

    for variant_obj in variant_res:
        # Populate variant case_display_name
        variant_case_obj = store.case(case_id=variant_obj["case_id"])
        if not variant_case_obj:
            # A variant with missing case was encountered
            continue
        case_display_name = variant_case_obj.get("display_name")
        variant_obj["case_display_name"] = case_display_name

        # hide other institutes for now
        other_institutes = set([variant_case_obj.get("owner")])
        other_institutes.update(set(variant_case_obj.get("collaborators", [])))
        if my_institutes.isdisjoint(other_institutes):
            # If the user does not have access to the information we skip it
            continue

        genome_build = get_genome_build(variant_case_obj)
        variant_genes = variant_obj.get("genes")
        gene_object = update_HGNC_symbols(store, variant_genes, genome_build)

        # Populate variant HGVS and predictions
        variant_genes = variant_obj.get("genes")
        hgvs_c = []
        hgvs_p = []
        if variant_genes is not None:
            for gene_obj in variant_genes:
                hgnc_id = gene_obj["hgnc_id"]
                gene_symbol = gene(store, hgnc_id)["symbol"]
                gene_symbols = [gene_symbol]

                # gather HGVS info from gene transcripts
                (hgvs_nucleotide, hgvs_protein) = get_hgvs(gene_obj)
                hgvs_c.append(hgvs_nucleotide)
                hgvs_p.append(hgvs_protein)

            if len(gene_symbols) == 1:
                variant_obj["hgvs"] = hgvs_str(gene_symbols, hgvs_p, hgvs_c)

            # populate variant predictions for display
            variant_obj.update(predictions(variant_genes))

        variants.append(variant_obj)

    return {"variants": variants, "more_variants": more_variants}
Exemplo n.º 6
0
def panel(panel_id):
    """Display (and add pending updates to) a specific gene panel."""

    panel_obj = store.gene_panel(panel_id) or store.panel(panel_id)
    if not panel_obj:
        flash("Panel with id {} not found.".format(panel_id), "warning")
        return redirect(url_for("panels.panels"))

    if request.method == "POST":
        if request.form.get("update_description"):
            panel_obj["description"] = request.form["panel_description"]

            if controllers.panel_write_granted(panel_obj, current_user):
                store.update_panel(panel_obj=panel_obj)
            else:
                flash(
                    "Permission denied: please ask a panel maintainer or admin for help.",
                    "danger",
                )
            return redirect(url_for("panels.panel", panel_id=panel_obj["_id"]))

        raw_hgnc_id = request.form["hgnc_id"]
        if "|" in raw_hgnc_id:
            raw_hgnc_id = raw_hgnc_id.split(" | ", 1)[0]
        hgnc_id = 0
        try:
            hgnc_id = int(raw_hgnc_id)
        except ValueError:
            flash("Provided HGNC is not valid : '{}'".format(raw_hgnc_id),
                  "danger")
            return redirect(request.referrer)
        action = request.form["action"]
        gene_obj = store.hgnc_gene_caption(
            hgnc_identifier=hgnc_id, build="37") or store.hgnc_gene_caption(
                hgnc_identifier=hgnc_id, build="38")
        if gene_obj is None:
            flash("HGNC id not found: {}".format(hgnc_id), "warning")
            return redirect(request.referrer)

        if action == "add":
            panel_gene = controllers.existing_gene(store, panel_obj, hgnc_id)
            if panel_gene:
                flash("gene already in panel: {}".format(panel_gene["symbol"]),
                      "warning")
            else:
                # ask user to fill-in more information about the gene
                return redirect(
                    url_for(".gene_edit", panel_id=panel_id, hgnc_id=hgnc_id))
        elif action == "delete":
            LOG.debug("marking gene to be deleted: %s", hgnc_id)
            panel_obj = store.add_pending(panel_obj, gene_obj, action="delete")
    data = controllers.panel(store, panel_obj)
    if request.args.get("case_id"):
        data["case"] = store.case(request.args["case_id"])
    if request.args.get("institute_id"):
        data["institute"] = store.institute(request.args["institute_id"])
    return data
Exemplo n.º 7
0
def causatives(institute_obj, request):
    """Create content to be displayed on institute causatives page

    Args:
        institute_obj(dict) An institute object
        request(flask.request) request sent by user's browser

    Returns:
        data(dict)
    """
    # Retrieve variants grouped by case
    query = request.args.get("query", "")
    hgnc_id = None
    if "|" in query:
        # filter accepts an array of IDs. Provide an array with one ID element
        try:
            hgnc_id = [int(query.split(" | ", 1)[0])]
        except ValueError:
            flash("Provided gene info could not be parsed!", "warning")

    variants = list(
        store.check_causatives(institute_obj=institute_obj,
                               limit_genes=hgnc_id))
    if variants:
        variants = sorted(
            variants,
            key=lambda k: k.get("hgnc_symbols", [None])[0] or k.get("str_repid"
                                                                    ) or "",
        )

    all_variants = {}
    all_cases = {}
    for variant_obj in variants:
        if variant_obj["category"] in ["snv", "cancer"]:
            update_representative_gene(variant_obj, variant_obj.get(
                "genes", []))  # required to display cDNA and protein change
        if variant_obj["case_id"] not in all_cases:
            case_obj = store.case(variant_obj["case_id"])
            all_cases[variant_obj["case_id"]] = case_obj
        else:
            case_obj = all_cases[variant_obj["case_id"]]

        if variant_obj["variant_id"] not in all_variants:
            all_variants[variant_obj["variant_id"]] = []

        all_variants[variant_obj["variant_id"]].append((case_obj, variant_obj))

    data = dict(
        institute=institute_obj,
        variant_groups=all_variants,
        acmg_map={
            key: ACMG_COMPLETE_MAP[value]
            for key, value in ACMG_MAP.items()
        },
    )
    return data
Exemplo n.º 8
0
def causatives(institute_id):
    institute_obj = institute_and_case(store, institute_id)
    variants = store.check_causatives(institute_obj=institute_obj)
    all_variants = {}
    all_cases = {}
    for variant_obj in variants:
        if variant_obj['case_id'] not in all_cases:
            case_obj = store.case(variant_obj['case_id'])
            all_cases[variant_obj['case_id']] = case_obj
        else:
            case_obj = all_cases[variant_obj['case_id']]

        if variant_obj['variant_id'] not in all_variants:
            all_variants[variant_obj['variant_id']] = []
        all_variants[variant_obj['variant_id']].append((case_obj, variant_obj))

    return dict(institute=institute_obj, variant_groups=all_variants)
Exemplo n.º 9
0
def causatives(institute_id):
    institute_obj = institute_and_case(store, institute_id)
    variants = store.check_causatives(institute_obj=institute_obj)
    all_variants = {}
    all_cases = {}
    for variant_obj in variants:
        if variant_obj['case_id'] not in all_cases:
            case_obj = store.case(variant_obj['case_id'])
            all_cases[variant_obj['case_id']] = case_obj
        else:
            case_obj = all_cases[variant_obj['case_id']]

        if variant_obj['variant_id'] not in all_variants:
            all_variants[variant_obj['variant_id']] = []
        all_variants[variant_obj['variant_id']].append((case_obj, variant_obj))

    return dict(institute=institute_obj, variant_groups=all_variants)
Exemplo n.º 10
0
def panel(panel_id):
    """Display (and add pending updates to) a specific gene panel."""
    panel_obj = store.gene_panel(panel_id) or store.panel(panel_id)

    if request.method == 'POST':
        if request.form.get('update_description'):
            panel_obj['description'] = request.form['panel_description']
            store.update_panel(panel_obj=panel_obj)
            return redirect( url_for('panels.panel', panel_id=panel_obj['_id']) )

        raw_hgnc_id = request.form['hgnc_id']
        if '|' in raw_hgnc_id:
            raw_hgnc_id = raw_hgnc_id.split(' | ', 1)[0]
        hgnc_id = 0
        try:
            hgnc_id = int(raw_hgnc_id)
        except:
            flash("Provided HGNC is not valid : '{}'". format(raw_hgnc_id), 'danger')
            return redirect(request.referrer)
        action = request.form['action']
        gene_obj = store.hgnc_gene(hgnc_id)
        if gene_obj is None:
            flash("HGNC id not found: {}".format(hgnc_id), 'warning')
            return redirect(request.referrer)

        if action == 'add':
            panel_gene = controllers.existing_gene(store, panel_obj, hgnc_id)
            if panel_gene:
                flash("gene already in panel: {}".format(panel_gene['symbol']),
                      'warning')
            else:
                # ask user to fill-in more information about the gene
                return redirect(url_for('.gene_edit', panel_id=panel_id,
                                        hgnc_id=hgnc_id))
        elif action == 'delete':
            log.debug("marking gene to be deleted: %s", hgnc_id)
            panel_obj = store.add_pending(panel_obj, gene_obj, action='delete')

    data = controllers.panel(store, panel_obj)
    if request.args.get('case_id'):
        data['case'] = store.case(request.args['case_id'])
    if request.args.get('institute_id'):
        data['institute'] = store.institute(request.args['institute_id'])
    return data
Exemplo n.º 11
0
def individual(case_id, ind, key, value):
    """Update information on individual level in Scout"""

    case_obj = store.case(case_id)
    if not case_obj:
        click.echo(f"Could not find case {case_id}")
        return
    individuals = {
        ind_info["display_name"]: ind_info
        for ind_info in case_obj["individuals"]
    }
    # If ind name is empty, print available individual names for this case to help the user to build the command
    if ind is None:
        click.echo(
            f"Please specify individual name with '-n' option. Available individuals for this case:{list(individuals.keys())}"
        )
        return
    if ind not in individuals:
        click.echo(
            f"Could not find individual '{ind}' in case individuals. Available individuals for this case: {list(individuals.keys())}"
        )
        return
    # If key is null or non-valid, print a list of all the keys that can be updated using this function
    if key is None or not key in UPDATE_KEYS:
        click.echo(
            f"Please specify a valid key to update. Valid keys:{ UPDATE_KEYS }"
        )
        return
    if value is None:
        click.echo(f"Please specify a file path for key {key}")
        return
    file_path = Path(value)
    # If file is not found on the server, ask if user wants to update the key anyway
    if file_path.exists() is False:
        click.confirm(
            "The provided path was not found on the server, update key anyway?",
            abort=True,
        )
    # perform the update
    for ind_obj in case_obj["individuals"]:
        if ind_obj["display_name"] == ind:
            ind_obj[key] = value

    store.update_case(case_obj)
Exemplo n.º 12
0
def gene_variants(store, pymongo_cursor, variant_count, page=1, per_page=50):
    """Pre-process list of variants."""

    skip_count = per_page * max(page - 1, 0)
    more_variants = True if variant_count > (skip_count + per_page) else False
    variant_res = pymongo_cursor.skip(skip_count).limit(per_page)
    variants = []

    for variant_obj in variant_res:
        # Populate variant case_display_name
        variant_case_obj = store.case(case_id=variant_obj["case_id"])
        case_display_name = variant_case_obj.get("display_name")
        variant_obj["case_display_name"] = case_display_name

        genome_build = get_genome_build(variant_case_obj)
        variant_genes = variant_obj.get("genes")
        update_HGNC_symbols(store, variant_genes, genome_build)

        # Populate variant HGVS and predictions
        variant_genes = variant_obj.get("genes")
        hgvs_c = []
        hgvs_p = []
        if variant_genes is not None:
            for gene_obj in variant_genes:
                hgnc_id = gene_obj["hgnc_id"]
                gene_caption = store.hgnc_gene_caption(hgnc_id)
                gene_symbols = [gene_caption["hgnc_symbol"]]

                # gather HGVS info from gene transcripts
                (hgvs_nucleotide, hgvs_protein) = get_hgvs(gene_obj)
                hgvs_c.append(hgvs_nucleotide)
                hgvs_p.append(hgvs_protein)

            if len(gene_symbols) == 1:
                variant_obj["hgvs"] = hgvs_str(gene_symbols, hgvs_p, hgvs_c)

            # populate variant predictions for display
            variant_obj.update(predictions(variant_genes))

        variants.append(variant_obj)

    return {"variants": variants, "more_variants": more_variants}
Exemplo n.º 13
0
def panel(panel_id):
    """Display (and add pending updates to) a specific gene panel."""
    panel_obj = store.gene_panel(panel_id) or store.panel(panel_id)
    if request.method == 'POST':
        raw_hgnc_id = request.form['hgnc_id']
        if '|' in raw_hgnc_id:
            raw_hgnc_id = raw_hgnc_id.split(' | ', 1)[0]
        hgnc_id = 0
        try:
            hgnc_id = int(raw_hgnc_id)
        except:
            flash("Provided HGNC is not valid : '{}'". format(raw_hgnc_id), 'danger')
            return redirect(request.referrer)
        action = request.form['action']
        gene_obj = store.hgnc_gene(hgnc_id)
        if gene_obj is None:
            flash("HGNC id not found: {}".format(hgnc_id), 'warning')
            return redirect(request.referrer)

        if action == 'add':
            panel_gene = controllers.existing_gene(store, panel_obj, hgnc_id)
            if panel_gene:
                flash("gene already in panel: {}".format(panel_gene['symbol']),
                      'warning')
            else:
                # ask user to fill-in more information about the gene
                return redirect(url_for('.gene_edit', panel_id=panel_id,
                                        hgnc_id=hgnc_id))
        elif action == 'delete':
            log.debug("marking gene to be deleted: %s", hgnc_id)
            panel_obj = store.add_pending(panel_obj, gene_obj, action='delete')

    data = controllers.panel(store, panel_obj)
    if request.args.get('case_id'):
        data['case'] = store.case(request.args['case_id'])
    if request.args.get('institute_id'):
        data['institute'] = store.institute(request.args['institute_id'])
    return data
Exemplo n.º 14
0
def causatives(institute_id):
    institute_obj = institute_and_case(store, institute_id)
    query = request.args.get("query", "")
    hgnc_id = None
    if "|" in query:
        # filter accepts an array of IDs. Provide an array with one ID element
        try:
            hgnc_id = [int(query.split(" | ", 1)[0])]
        except ValueError:
            flash("Provided gene info could not be parsed!", "warning")

    variants = store.check_causatives(institute_obj=institute_obj,
                                      limit_genes=hgnc_id)
    if variants:
        variants.sort("hgnc_symbols", pymongo.ASCENDING)
    all_variants = {}
    all_cases = {}
    for variant_obj in variants:
        if variant_obj["case_id"] not in all_cases:
            case_obj = store.case(variant_obj["case_id"])
            all_cases[variant_obj["case_id"]] = case_obj
        else:
            case_obj = all_cases[variant_obj["case_id"]]

        if variant_obj["variant_id"] not in all_variants:
            all_variants[variant_obj["variant_id"]] = []

        all_variants[variant_obj["variant_id"]].append((case_obj, variant_obj))

    acmg_map = {
        key: ACMG_COMPLETE_MAP[value]
        for key, value in ACMG_MAP.items()
    }

    return dict(institute=institute_obj,
                variant_groups=all_variants,
                acmg_map=acmg_map)